bare-script 3.8.2__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.
- bare_script/__init__.py +37 -0
- bare_script/__main__.py +12 -0
- bare_script/bare.py +165 -0
- bare_script/baredoc.py +177 -0
- bare_script/data.py +477 -0
- bare_script/include/__init__.py +0 -0
- bare_script/include/args.bare +340 -0
- bare_script/include/baredoc.bare +313 -0
- bare_script/include/dataLineChart.bare +90 -0
- bare_script/include/dataTable.bare +204 -0
- bare_script/include/diff.bare +148 -0
- bare_script/include/forms.bare +72 -0
- bare_script/include/markdownUp.bare +662 -0
- bare_script/include/pager.bare +301 -0
- bare_script/include/unittest.bare +529 -0
- bare_script/include/unittestMock.bare +456 -0
- bare_script/library.py +2273 -0
- bare_script/model.py +547 -0
- bare_script/options.py +119 -0
- bare_script/parser.py +859 -0
- bare_script/runtime.py +471 -0
- bare_script/value.py +530 -0
- bare_script-3.8.2.dist-info/METADATA +201 -0
- bare_script-3.8.2.dist-info/RECORD +28 -0
- bare_script-3.8.2.dist-info/WHEEL +5 -0
- bare_script-3.8.2.dist-info/entry_points.txt +3 -0
- bare_script-3.8.2.dist-info/licenses/LICENSE +21 -0
- bare_script-3.8.2.dist-info/top_level.txt +1 -0
bare_script/library.py
ADDED
|
@@ -0,0 +1,2273 @@
|
|
|
1
|
+
# Licensed under the MIT License
|
|
2
|
+
# https://github.com/craigahobbs/bare-script-py/blob/main/LICENSE
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
The BareScript library
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import calendar
|
|
9
|
+
import csv
|
|
10
|
+
import datetime
|
|
11
|
+
import functools
|
|
12
|
+
import json
|
|
13
|
+
import math
|
|
14
|
+
import random
|
|
15
|
+
import re
|
|
16
|
+
import urllib
|
|
17
|
+
|
|
18
|
+
from schema_markdown import TYPE_MODEL, parse_schema_markdown, validate_type, validate_type_model
|
|
19
|
+
|
|
20
|
+
from .data import aggregate_data, add_calculated_field, filter_data, join_data, sort_data, top_data, validate_data
|
|
21
|
+
from .value import R_NUMBER_CLEANUP, ValueArgsError, value_args_model, value_args_validate, \
|
|
22
|
+
value_boolean, value_compare, value_is, value_json, value_normalize_datetime, value_parse_datetime, \
|
|
23
|
+
value_parse_integer, value_parse_number, value_round_number, value_string, value_type
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
# The default maximum statements for executeScript
|
|
27
|
+
DEFAULT_MAX_STATEMENTS = 1e9
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
#
|
|
31
|
+
# Array functions
|
|
32
|
+
#
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
# $function: arrayCopy
|
|
36
|
+
# $group: array
|
|
37
|
+
# $doc: Create a copy of an array
|
|
38
|
+
# $arg array: The array to copy
|
|
39
|
+
# $return: The array copy
|
|
40
|
+
def _array_copy(args, unused_options):
|
|
41
|
+
array, = value_args_validate(_ARRAY_COPY_ARGS, args)
|
|
42
|
+
return list(array)
|
|
43
|
+
|
|
44
|
+
_ARRAY_COPY_ARGS = value_args_model([
|
|
45
|
+
{'name': 'array', 'type': 'array'}
|
|
46
|
+
])
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
# $function: arrayDelete
|
|
50
|
+
# $group: array
|
|
51
|
+
# $doc: Delete an array element
|
|
52
|
+
# $arg array: The array
|
|
53
|
+
# $arg index: The array element's index
|
|
54
|
+
# $return: The array element
|
|
55
|
+
def _array_delete(args, unused_options):
|
|
56
|
+
array, index = value_args_validate(_ARRAY_DELETE_ARGS, args)
|
|
57
|
+
if index >= len(array):
|
|
58
|
+
raise ValueArgsError('index', index)
|
|
59
|
+
|
|
60
|
+
del array[int(index)]
|
|
61
|
+
|
|
62
|
+
_ARRAY_DELETE_ARGS = value_args_model([
|
|
63
|
+
{'name': 'array', 'type': 'array'},
|
|
64
|
+
{'name': 'index', 'type': 'number', 'integer': True, 'gte': 0}
|
|
65
|
+
])
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
# $function: arrayExtend
|
|
69
|
+
# $group: array
|
|
70
|
+
# $doc: Extend one array with another
|
|
71
|
+
# $arg array: The array to extend
|
|
72
|
+
# $arg array2: The array to extend with
|
|
73
|
+
# $return: The extended array
|
|
74
|
+
def _array_extend(args, unused_options):
|
|
75
|
+
array, array2 = value_args_validate(_ARRAY_EXTEND_ARGS, args)
|
|
76
|
+
array.extend(array2)
|
|
77
|
+
return array
|
|
78
|
+
|
|
79
|
+
_ARRAY_EXTEND_ARGS = value_args_model([
|
|
80
|
+
{'name': 'array', 'type': 'array'},
|
|
81
|
+
{'name': 'array2', 'type': 'array'}
|
|
82
|
+
])
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
# $function: arrayFlat
|
|
86
|
+
# $group: array
|
|
87
|
+
# $doc: Flat an array hierarchy
|
|
88
|
+
# $arg array: The array to flat
|
|
89
|
+
# $arg depth: The maximum depth of the array hierarchy
|
|
90
|
+
# $return: The flated array
|
|
91
|
+
def _array_flat(args, unused_options):
|
|
92
|
+
array, depth = value_args_validate(_ARRAY_FLAT_ARGS, args)
|
|
93
|
+
return list(_array_flat_helper(array, 0, depth))
|
|
94
|
+
|
|
95
|
+
def _array_flat_helper(array, depth, max_depth):
|
|
96
|
+
if max_depth < depth:
|
|
97
|
+
yield array
|
|
98
|
+
return
|
|
99
|
+
|
|
100
|
+
for item in array:
|
|
101
|
+
if isinstance(item, list):
|
|
102
|
+
yield from _array_flat_helper(item, depth + 1, max_depth)
|
|
103
|
+
else:
|
|
104
|
+
yield item
|
|
105
|
+
|
|
106
|
+
_ARRAY_FLAT_ARGS = value_args_model([
|
|
107
|
+
{'name': 'array', 'type': 'array'},
|
|
108
|
+
{'name': 'depth', 'type': 'number', 'integer': True, 'default': 10}
|
|
109
|
+
])
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
# $function: arrayGet
|
|
113
|
+
# $group: array
|
|
114
|
+
# $doc: Get an array element
|
|
115
|
+
# $arg array: The array
|
|
116
|
+
# $arg index: The array element's index
|
|
117
|
+
# $return: The array element
|
|
118
|
+
def _array_get(args, unused_options):
|
|
119
|
+
array, index = value_args_validate(_ARRAY_GET_ARGS, args)
|
|
120
|
+
if index >= len(array):
|
|
121
|
+
raise ValueArgsError('index', index)
|
|
122
|
+
|
|
123
|
+
return array[int(index)]
|
|
124
|
+
|
|
125
|
+
_ARRAY_GET_ARGS = value_args_model([
|
|
126
|
+
{'name': 'array', 'type': 'array'},
|
|
127
|
+
{'name': 'index', 'type': 'number', 'integer': True, 'gte': 0}
|
|
128
|
+
])
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
# $function: arrayIndexOf
|
|
132
|
+
# $group: array
|
|
133
|
+
# $doc: Find the index of a value in an array
|
|
134
|
+
# $arg array: The array
|
|
135
|
+
# $arg value: The value to find in the array, or a match function, f(value) -> bool
|
|
136
|
+
# $arg index: Optional (default is 0). The index at which to start the search.
|
|
137
|
+
# $return: The first index of the value in the array; -1 if not found.
|
|
138
|
+
def _array_index_of(args, options):
|
|
139
|
+
array, value, index = value_args_validate(_ARRAY_INDEX_OF_ARGS, args, -1)
|
|
140
|
+
if index >= len(array):
|
|
141
|
+
raise ValueArgsError('index', index, -1)
|
|
142
|
+
|
|
143
|
+
# Value function?
|
|
144
|
+
if value_type(value) == 'function':
|
|
145
|
+
for ix in range(int(index), len(array)):
|
|
146
|
+
if value_boolean(value([array[ix]], options)):
|
|
147
|
+
return ix
|
|
148
|
+
else:
|
|
149
|
+
for ix in range(int(index), len(array)):
|
|
150
|
+
if value_compare(array[ix], value) == 0:
|
|
151
|
+
return ix
|
|
152
|
+
|
|
153
|
+
return -1
|
|
154
|
+
|
|
155
|
+
_ARRAY_INDEX_OF_ARGS = value_args_model([
|
|
156
|
+
{'name': 'array', 'type': 'array'},
|
|
157
|
+
{'name': 'value'},
|
|
158
|
+
{'name': 'index', 'type': 'number', 'default': 0, 'integer': True, 'gte': 0}
|
|
159
|
+
])
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
# $function: arrayJoin
|
|
163
|
+
# $group: array
|
|
164
|
+
# $doc: Join an array with a separator string
|
|
165
|
+
# $arg array: The array
|
|
166
|
+
# $arg separator: The separator string
|
|
167
|
+
# $return: The joined string
|
|
168
|
+
def _array_join(args, unused_options):
|
|
169
|
+
array, separator = value_args_validate(_ARRAY_JOIN_ARGS, args)
|
|
170
|
+
return separator.join(value_string(value) for value in array)
|
|
171
|
+
|
|
172
|
+
_ARRAY_JOIN_ARGS = value_args_model([
|
|
173
|
+
{'name': 'array', 'type': 'array'},
|
|
174
|
+
{'name': 'separator', 'type': 'string'}
|
|
175
|
+
])
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
# $function: arrayLastIndexOf
|
|
179
|
+
# $group: array
|
|
180
|
+
# $doc: Find the last index of a value in an array
|
|
181
|
+
# $arg array: The array
|
|
182
|
+
# $arg value: The value to find in the array, or a match function, f(value) -> bool
|
|
183
|
+
# $arg index: Optional (default is the end of the array). The index at which to start the search.
|
|
184
|
+
# $return: The last index of the value in the array; -1 if not found.
|
|
185
|
+
def _array_last_index_of(args, options):
|
|
186
|
+
array, value, index = value_args_validate(_ARRAY_LAST_INDEX_OF_ARGS, args, -1)
|
|
187
|
+
if index is None:
|
|
188
|
+
index = len(array) - 1
|
|
189
|
+
if index >= len(array):
|
|
190
|
+
raise ValueArgsError('index', index, -1)
|
|
191
|
+
|
|
192
|
+
# Value function?
|
|
193
|
+
if value_type(value) == 'function':
|
|
194
|
+
for ix in range(int(index), -1, -1):
|
|
195
|
+
if value_boolean(value([array[ix]], options)):
|
|
196
|
+
return ix
|
|
197
|
+
else:
|
|
198
|
+
for ix in range(int(index), -1, -1):
|
|
199
|
+
if value_compare(array[ix], value) == 0:
|
|
200
|
+
return ix
|
|
201
|
+
|
|
202
|
+
return -1
|
|
203
|
+
|
|
204
|
+
_ARRAY_LAST_INDEX_OF_ARGS = value_args_model([
|
|
205
|
+
{'name': 'array', 'type': 'array'},
|
|
206
|
+
{'name': 'value'},
|
|
207
|
+
{'name': 'index', 'type': 'number', 'nullable': True, 'integer': True, 'gte': 0}
|
|
208
|
+
])
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
# $function: arrayLength
|
|
212
|
+
# $group: array
|
|
213
|
+
# $doc: Get the length of an array
|
|
214
|
+
# $arg array: The array
|
|
215
|
+
# $return: The array's length; zero if not an array
|
|
216
|
+
def _array_length(args, unused_options):
|
|
217
|
+
array, = value_args_validate(_ARRAY_LENGTH_ARGS, args, 0)
|
|
218
|
+
return len(array)
|
|
219
|
+
|
|
220
|
+
_ARRAY_LENGTH_ARGS = value_args_model([
|
|
221
|
+
{'name': 'array', 'type': 'array'}
|
|
222
|
+
])
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
# $function: arrayNew
|
|
226
|
+
# $group: array
|
|
227
|
+
# $doc: Create a new array
|
|
228
|
+
# $arg values...: The new array's values
|
|
229
|
+
# $return: The new array
|
|
230
|
+
def _array_new(args, unused_options):
|
|
231
|
+
return args
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
# $function: arrayNewSize
|
|
235
|
+
# $group: array
|
|
236
|
+
# $doc: Create a new array of a specific size
|
|
237
|
+
# $arg size: Optional (default is 0). The new array's size.
|
|
238
|
+
# $arg value: Optional (default is 0). The value with which to fill the new array.
|
|
239
|
+
# $return: The new array
|
|
240
|
+
def _array_new_size(args, unused_options):
|
|
241
|
+
size, value = value_args_validate(_ARRAY_NEW_SIZE_ARGS, args)
|
|
242
|
+
return list(value for _ in range(int(size)))
|
|
243
|
+
|
|
244
|
+
_ARRAY_NEW_SIZE_ARGS = value_args_model([
|
|
245
|
+
{'name': 'size', 'type': 'number', 'default': 0, 'integer': True, 'gte': 0},
|
|
246
|
+
{'name': 'value', 'default': 0}
|
|
247
|
+
])
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
# $function: arrayPop
|
|
251
|
+
# $group: array
|
|
252
|
+
# $doc: Remove the last element of the array and return it
|
|
253
|
+
# $arg array: The array
|
|
254
|
+
# $return: The last element of the array; null if the array is empty.
|
|
255
|
+
def _array_pop(args, unused_options):
|
|
256
|
+
array, = value_args_validate(_ARRAY_POP_ARGS, args)
|
|
257
|
+
if len(array) == 0:
|
|
258
|
+
raise ValueArgsError('array', array)
|
|
259
|
+
|
|
260
|
+
return array.pop()
|
|
261
|
+
|
|
262
|
+
_ARRAY_POP_ARGS = value_args_model([
|
|
263
|
+
{'name': 'array', 'type': 'array'}
|
|
264
|
+
])
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
# $function: arrayPush
|
|
268
|
+
# $group: array
|
|
269
|
+
# $doc: Add one or more values to the end of the array
|
|
270
|
+
# $arg array: The array
|
|
271
|
+
# $arg values...: The values to add to the end of the array
|
|
272
|
+
# $return: The array
|
|
273
|
+
def _array_push(args, unused_options):
|
|
274
|
+
array, values = value_args_validate(_ARRAY_PUSH_ARGS, args)
|
|
275
|
+
array.extend(values)
|
|
276
|
+
return array
|
|
277
|
+
|
|
278
|
+
_ARRAY_PUSH_ARGS = value_args_model([
|
|
279
|
+
{'name': 'array', 'type': 'array'},
|
|
280
|
+
{'name': 'values', 'lastArgArray': True}
|
|
281
|
+
])
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
# $function: arraySet
|
|
285
|
+
# $group: array
|
|
286
|
+
# $doc: Set an array element value
|
|
287
|
+
# $arg array: The array
|
|
288
|
+
# $arg index: The index of the element to set
|
|
289
|
+
# $arg value: The value to set
|
|
290
|
+
# $return: The value
|
|
291
|
+
def _array_set(args, unused_options):
|
|
292
|
+
array, index, value = value_args_validate(_ARRAY_SET_ARGS, args)
|
|
293
|
+
if index >= len(array):
|
|
294
|
+
raise ValueArgsError('index', index)
|
|
295
|
+
|
|
296
|
+
array[int(index)] = value
|
|
297
|
+
return value
|
|
298
|
+
|
|
299
|
+
_ARRAY_SET_ARGS = value_args_model([
|
|
300
|
+
{'name': 'array', 'type': 'array'},
|
|
301
|
+
{'name': 'index', 'type': 'number', 'integer': True, 'gte': 0},
|
|
302
|
+
{'name': 'value'}
|
|
303
|
+
])
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
# $function: arrayShift
|
|
307
|
+
# $group: array
|
|
308
|
+
# $doc: Remove the first element of the array and return it
|
|
309
|
+
# $arg array: The array
|
|
310
|
+
# $return: The first element of the array; null if the array is empty.
|
|
311
|
+
def _array_shift(args, unused_options):
|
|
312
|
+
array, = value_args_validate(_ARRAY_SHIFT_ARGS, args)
|
|
313
|
+
if len(array) == 0:
|
|
314
|
+
raise ValueArgsError('array', array)
|
|
315
|
+
|
|
316
|
+
result = array[0]
|
|
317
|
+
del array[0]
|
|
318
|
+
return result
|
|
319
|
+
|
|
320
|
+
_ARRAY_SHIFT_ARGS = value_args_model([
|
|
321
|
+
{'name': 'array', 'type': 'array'}
|
|
322
|
+
])
|
|
323
|
+
|
|
324
|
+
|
|
325
|
+
# $function: arraySlice
|
|
326
|
+
# $group: array
|
|
327
|
+
# $doc: Copy a portion of an array
|
|
328
|
+
# $arg array: The array
|
|
329
|
+
# $arg start: Optional (default is 0). The start index of the slice.
|
|
330
|
+
# $arg end: Optional (default is the end of the array). The end index of the slice.
|
|
331
|
+
# $return: The new array slice
|
|
332
|
+
def _array_slice(args, unused_options):
|
|
333
|
+
array, start, end = value_args_validate(_ARRAY_SLICE_ARGS, args)
|
|
334
|
+
if end is None:
|
|
335
|
+
end = len(array)
|
|
336
|
+
if start > len(array):
|
|
337
|
+
raise ValueArgsError('start', start)
|
|
338
|
+
if end > len(array):
|
|
339
|
+
raise ValueArgsError('end', end)
|
|
340
|
+
|
|
341
|
+
return array[int(start):int(end)]
|
|
342
|
+
|
|
343
|
+
_ARRAY_SLICE_ARGS = value_args_model([
|
|
344
|
+
{'name': 'array', 'type': 'array'},
|
|
345
|
+
{'name': 'start', 'type': 'number', 'default': 0, 'integer': True, 'gte': 0},
|
|
346
|
+
{'name': 'end', 'type': 'number', 'nullable': True, 'integer': True, 'gte': 0}
|
|
347
|
+
])
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
# $function: arraySort
|
|
351
|
+
# $group: array
|
|
352
|
+
# $doc: Sort an array
|
|
353
|
+
# $arg array: The array
|
|
354
|
+
# $arg compareFn: Optional (default is null). The comparison function.
|
|
355
|
+
# $return: The sorted array
|
|
356
|
+
def _array_sort(args, options):
|
|
357
|
+
array, compare_fn = value_args_validate(_ARRAY_SORT_ARGS, args)
|
|
358
|
+
if compare_fn is None:
|
|
359
|
+
array.sort(key=functools.cmp_to_key(value_compare))
|
|
360
|
+
else:
|
|
361
|
+
array.sort(key=functools.cmp_to_key(lambda v1, v2: compare_fn([v1, v2], options)))
|
|
362
|
+
return array
|
|
363
|
+
|
|
364
|
+
_ARRAY_SORT_ARGS = value_args_model([
|
|
365
|
+
{'name': 'array', 'type': 'array'},
|
|
366
|
+
{'name': 'compareFn', 'type': 'function', 'nullable': True}
|
|
367
|
+
])
|
|
368
|
+
|
|
369
|
+
|
|
370
|
+
#
|
|
371
|
+
# Coverage functions
|
|
372
|
+
#
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
# Coverage configuration object global variable name
|
|
376
|
+
COVERAGE_GLOBAL_NAME = '__bareScriptCoverage'
|
|
377
|
+
|
|
378
|
+
|
|
379
|
+
# $function: coverageGlobalGet
|
|
380
|
+
# $group: coverage
|
|
381
|
+
# $doc: Get the coverage global object
|
|
382
|
+
# $return: The [coverage global object](https://craigahobbs.github.io/bare-script-py/model/#var.vName='CoverageGlobal')
|
|
383
|
+
def _coverage_global_get(unused_args, options):
|
|
384
|
+
globals_ = options.get('globals') if options is not None else None
|
|
385
|
+
return globals_.get(COVERAGE_GLOBAL_NAME) if globals_ is not None else None
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
# $function: coverageGlobalName
|
|
389
|
+
# $group: coverage
|
|
390
|
+
# $doc: Get the coverage global variable name
|
|
391
|
+
# $return: The coverage global variable name
|
|
392
|
+
def _coverage_global_name(unused_args, unused_options):
|
|
393
|
+
return COVERAGE_GLOBAL_NAME
|
|
394
|
+
|
|
395
|
+
|
|
396
|
+
# $function: coverageStart
|
|
397
|
+
# $group: coverage
|
|
398
|
+
# $doc: Start coverage data collection
|
|
399
|
+
def _coverage_start(unused_args, options):
|
|
400
|
+
globals_ = options.get('globals') if options is not None else None
|
|
401
|
+
if globals_ is not None:
|
|
402
|
+
coverage_global = {'enabled': True}
|
|
403
|
+
globals_[COVERAGE_GLOBAL_NAME] = coverage_global
|
|
404
|
+
|
|
405
|
+
|
|
406
|
+
# $function: coverageStop
|
|
407
|
+
# $group: coverage
|
|
408
|
+
# $doc: Stop coverage data collection
|
|
409
|
+
def _coverage_stop(unused_args, options):
|
|
410
|
+
globals_ = options.get('globals') if options is not None else None
|
|
411
|
+
if globals_ is not None:
|
|
412
|
+
coverage_global = globals_.get(COVERAGE_GLOBAL_NAME)
|
|
413
|
+
if coverage_global is not None:
|
|
414
|
+
globals_[COVERAGE_GLOBAL_NAME]['enabled'] = False
|
|
415
|
+
|
|
416
|
+
|
|
417
|
+
#
|
|
418
|
+
# Data functions
|
|
419
|
+
#
|
|
420
|
+
|
|
421
|
+
|
|
422
|
+
# $function: dataAggregate
|
|
423
|
+
# $group: data
|
|
424
|
+
# $doc: Aggregate a data array
|
|
425
|
+
# $arg data: The data array
|
|
426
|
+
# $arg aggregation: The [aggregation model](https://craigahobbs.github.io/bare-script-py/library/model.html#var.vName='Aggregation')
|
|
427
|
+
# $return: The aggregated data array
|
|
428
|
+
def _data_aggregate(args, unused_options):
|
|
429
|
+
data, aggregation = value_args_validate(_DATA_AGGREGATE_ARGS, args)
|
|
430
|
+
return aggregate_data(data, aggregation)
|
|
431
|
+
|
|
432
|
+
_DATA_AGGREGATE_ARGS = value_args_model([
|
|
433
|
+
{'name': 'data', 'type': 'array'},
|
|
434
|
+
{'name': 'aggregation', 'type': 'object'}
|
|
435
|
+
])
|
|
436
|
+
|
|
437
|
+
|
|
438
|
+
# $function: dataCalculatedField
|
|
439
|
+
# $group: data
|
|
440
|
+
# $doc: Add a calculated field to a data array
|
|
441
|
+
# $arg data: The data array
|
|
442
|
+
# $arg fieldName: The calculated field name
|
|
443
|
+
# $arg expr: The calculated field expression
|
|
444
|
+
# $arg variables: Optional (default is null). A variables object the expression evaluation.
|
|
445
|
+
# $return: The updated data array
|
|
446
|
+
def _data_calculated_field(args, options):
|
|
447
|
+
data, field_name, expr, variables = value_args_validate(_DATA_CALCULATED_FIELD_ARGS, args)
|
|
448
|
+
return add_calculated_field(data, field_name, expr, variables, options)
|
|
449
|
+
|
|
450
|
+
_DATA_CALCULATED_FIELD_ARGS = value_args_model([
|
|
451
|
+
{'name': 'data', 'type': 'array'},
|
|
452
|
+
{'name': 'fieldName', 'type': 'string'},
|
|
453
|
+
{'name': 'expr', 'type': 'string'},
|
|
454
|
+
{'name': 'variables', 'type': 'object', 'nullable': True}
|
|
455
|
+
])
|
|
456
|
+
|
|
457
|
+
|
|
458
|
+
# $function: dataFilter
|
|
459
|
+
# $group: data
|
|
460
|
+
# $doc: Filter a data array
|
|
461
|
+
# $arg data: The data array
|
|
462
|
+
# $arg expr: The filter expression
|
|
463
|
+
# $arg variables: Optional (default is null). A variables object the expression evaluation.
|
|
464
|
+
# $return: The filtered data array
|
|
465
|
+
def _data_filter(args, options):
|
|
466
|
+
data, expr, variables = value_args_validate(_DATA_FILTER_ARGS, args)
|
|
467
|
+
return filter_data(data, expr, variables, options)
|
|
468
|
+
|
|
469
|
+
_DATA_FILTER_ARGS = value_args_model([
|
|
470
|
+
{'name': 'data', 'type': 'array'},
|
|
471
|
+
{'name': 'expr', 'type': 'string'},
|
|
472
|
+
{'name': 'variables', 'type': 'object', 'nullable': True}
|
|
473
|
+
])
|
|
474
|
+
|
|
475
|
+
|
|
476
|
+
# $function: dataJoin
|
|
477
|
+
# $group: data
|
|
478
|
+
# $doc: Join two data arrays
|
|
479
|
+
# $arg leftData: The left data array
|
|
480
|
+
# $arg rightData: The right data array
|
|
481
|
+
# $arg joinExpr: The [join expression](https://craigahobbs.github.io/bare-script-py/language/#expressions)
|
|
482
|
+
# $arg rightExpr: Optional (default is null).
|
|
483
|
+
# $arg rightExpr: The right [join expression](https://craigahobbs.github.io/bare-script-py/language/#expressions)
|
|
484
|
+
# $arg isLeftJoin: Optional (default is false). If true, perform a left join (always include left row).
|
|
485
|
+
# $arg variables: Optional (default is null). A variables object for join expression evaluation.
|
|
486
|
+
# $return: The joined data array
|
|
487
|
+
def _data_join(args, options):
|
|
488
|
+
left_data, right_data, join_expr, right_expr, is_left_join, variables = value_args_validate(_DATA_JOIN_ARGS, args)
|
|
489
|
+
return join_data(left_data, right_data, join_expr, right_expr, is_left_join, variables, options)
|
|
490
|
+
|
|
491
|
+
_DATA_JOIN_ARGS = value_args_model([
|
|
492
|
+
{'name': 'leftData', 'type': 'array'},
|
|
493
|
+
{'name': 'rightData', 'type': 'array'},
|
|
494
|
+
{'name': 'joinExpr', 'type': 'string'},
|
|
495
|
+
{'name': 'rightExpr', 'type': 'string', 'nullable': True},
|
|
496
|
+
{'name': 'isLeftJoin', 'type': 'boolean', 'default': False},
|
|
497
|
+
{'name': 'variables', 'type': 'object', 'nullable': True}
|
|
498
|
+
])
|
|
499
|
+
|
|
500
|
+
|
|
501
|
+
# $function: dataParseCSV
|
|
502
|
+
# $group: data
|
|
503
|
+
# $doc: Parse CSV text to a data array
|
|
504
|
+
# $arg text...: The CSV text
|
|
505
|
+
# $return: The data array
|
|
506
|
+
def _data_parse_csv(args, unused_options):
|
|
507
|
+
# Split the input CSV parts into lines
|
|
508
|
+
lines = []
|
|
509
|
+
for arg in args:
|
|
510
|
+
if arg is None:
|
|
511
|
+
continue
|
|
512
|
+
if value_type(arg) != 'string':
|
|
513
|
+
return None
|
|
514
|
+
lines.extend(arg.splitlines())
|
|
515
|
+
|
|
516
|
+
# Parse the CSV
|
|
517
|
+
data = list(csv.DictReader(lines, skipinitialspace=True))
|
|
518
|
+
|
|
519
|
+
# Validate the data (as CSV)
|
|
520
|
+
validate_data(data, True)
|
|
521
|
+
return data
|
|
522
|
+
|
|
523
|
+
|
|
524
|
+
# $function: dataSort
|
|
525
|
+
# $group: data
|
|
526
|
+
# $doc: Sort a data array
|
|
527
|
+
# $arg data: The data array
|
|
528
|
+
# $arg sorts: The sort field-name/descending-sort tuples
|
|
529
|
+
# $return: The sorted data array
|
|
530
|
+
def _data_sort(args, unused_options):
|
|
531
|
+
data, sorts = value_args_validate(_DATA_SORT_ARGS, args)
|
|
532
|
+
return sort_data(data, sorts)
|
|
533
|
+
|
|
534
|
+
_DATA_SORT_ARGS = value_args_model([
|
|
535
|
+
{'name': 'data', 'type': 'array'},
|
|
536
|
+
{'name': 'sorts', 'type': 'array'}
|
|
537
|
+
])
|
|
538
|
+
|
|
539
|
+
|
|
540
|
+
# $function: dataTop
|
|
541
|
+
# $group: data
|
|
542
|
+
# $doc: Keep the top rows for each category
|
|
543
|
+
# $arg data: The data array
|
|
544
|
+
# $arg count: The number of rows to keep (default is 1)
|
|
545
|
+
# $arg categoryFields: Optional (default is null). The category fields.
|
|
546
|
+
# $return: The top data array
|
|
547
|
+
def _data_top(args, unused_options):
|
|
548
|
+
data, count, category_fields = value_args_validate(_DATA_TOP_ARGS, args)
|
|
549
|
+
return top_data(data, count, category_fields)
|
|
550
|
+
|
|
551
|
+
_DATA_TOP_ARGS = value_args_model([
|
|
552
|
+
{'name': 'data', 'type': 'array'},
|
|
553
|
+
{'name': 'count', 'type': 'number', 'integer': True, 'gte': 1},
|
|
554
|
+
{'name': 'categoryFields', 'type': 'array', 'nullable': True}
|
|
555
|
+
])
|
|
556
|
+
|
|
557
|
+
|
|
558
|
+
# $function: dataValidate
|
|
559
|
+
# $group: data
|
|
560
|
+
# $doc: Validate a data array
|
|
561
|
+
# $arg data: The data array
|
|
562
|
+
# $arg csv: Optional (default is false). If true, parse value strings.
|
|
563
|
+
# $return: The validated data array
|
|
564
|
+
def _data_validate(args, unused_options):
|
|
565
|
+
data, csv_ = value_args_validate(_DATA_VALIDATE_ARGS, args)
|
|
566
|
+
validate_data(data, csv_)
|
|
567
|
+
return data
|
|
568
|
+
|
|
569
|
+
_DATA_VALIDATE_ARGS = value_args_model([
|
|
570
|
+
{'name': 'data', 'type': 'array'},
|
|
571
|
+
{'name': 'csv', 'type': 'boolean', 'default': False}
|
|
572
|
+
])
|
|
573
|
+
|
|
574
|
+
|
|
575
|
+
#
|
|
576
|
+
# Datetime functions
|
|
577
|
+
#
|
|
578
|
+
|
|
579
|
+
|
|
580
|
+
# $function: datetimeDay
|
|
581
|
+
# $group: datetime
|
|
582
|
+
# $doc: Get the day of the month of a datetime
|
|
583
|
+
# $arg datetime: The datetime
|
|
584
|
+
# $return: The day of the month
|
|
585
|
+
def _datetime_day(args, unused_options):
|
|
586
|
+
datetime_, = value_args_validate(_DATETIME_DAY_ARGS, args)
|
|
587
|
+
return value_normalize_datetime(datetime_).day
|
|
588
|
+
|
|
589
|
+
_DATETIME_DAY_ARGS = value_args_model([
|
|
590
|
+
{'name': 'datetime', 'type': 'datetime'}
|
|
591
|
+
])
|
|
592
|
+
|
|
593
|
+
|
|
594
|
+
# $function: datetimeHour
|
|
595
|
+
# $group: datetime
|
|
596
|
+
# $doc: Get the hour of a datetime
|
|
597
|
+
# $arg datetime: The datetime
|
|
598
|
+
# $return: The hour
|
|
599
|
+
def _datetime_hour(args, unused_options):
|
|
600
|
+
datetime_, = value_args_validate(_DATETIME_HOUR_ARGS, args)
|
|
601
|
+
return value_normalize_datetime(datetime_).hour
|
|
602
|
+
|
|
603
|
+
_DATETIME_HOUR_ARGS = value_args_model([
|
|
604
|
+
{'name': 'datetime', 'type': 'datetime'}
|
|
605
|
+
])
|
|
606
|
+
|
|
607
|
+
|
|
608
|
+
# $function: datetimeISOFormat
|
|
609
|
+
# $group: datetime
|
|
610
|
+
# $doc: Format the datetime as an ISO date/time string
|
|
611
|
+
# $arg datetime: The datetime
|
|
612
|
+
# $arg isDate: If true, format the datetime as an ISO date
|
|
613
|
+
# $return: The formatted datetime string
|
|
614
|
+
def _datetime_iso_format(args, unused_options):
|
|
615
|
+
datetime_arg, is_date = value_args_validate(_DATETIMEISO_FORMAT_ARGS, args)
|
|
616
|
+
|
|
617
|
+
datetime_ = value_normalize_datetime(datetime_arg)
|
|
618
|
+
if is_date:
|
|
619
|
+
return datetime.date(datetime_.year, datetime_.month, datetime_.day).isoformat()
|
|
620
|
+
|
|
621
|
+
return value_string(datetime_)
|
|
622
|
+
|
|
623
|
+
_DATETIMEISO_FORMAT_ARGS = value_args_model([
|
|
624
|
+
{'name': 'datetime', 'type': 'datetime'},
|
|
625
|
+
{'name': 'isDate', 'type': 'boolean', 'default': False}
|
|
626
|
+
])
|
|
627
|
+
|
|
628
|
+
|
|
629
|
+
# $function: datetimeISOParse
|
|
630
|
+
# $group: datetime
|
|
631
|
+
# $doc: Parse an ISO date/time string
|
|
632
|
+
# $arg string: The ISO date/time string
|
|
633
|
+
# $return: The datetime, or null if parsing fails
|
|
634
|
+
def _datetime_iso_parse(args, unused_options):
|
|
635
|
+
string, = value_args_validate(_DATETIMEISO_PARSE_ARGS, args)
|
|
636
|
+
return value_parse_datetime(string)
|
|
637
|
+
|
|
638
|
+
_DATETIMEISO_PARSE_ARGS = value_args_model([
|
|
639
|
+
{'name': 'string', 'type': 'string'}
|
|
640
|
+
])
|
|
641
|
+
|
|
642
|
+
|
|
643
|
+
# $function: datetimeMillisecond
|
|
644
|
+
# $group: datetime
|
|
645
|
+
# $doc: Get the millisecond of a datetime
|
|
646
|
+
# $arg datetime: The datetime
|
|
647
|
+
# $return: The millisecond
|
|
648
|
+
def _datetime_millisecond(args, unused_options):
|
|
649
|
+
datetime_, = value_args_validate(_DATETIME_MILLISECOND_ARGS, args)
|
|
650
|
+
return int(value_round_number(value_normalize_datetime(datetime_).microsecond / 1000, 0))
|
|
651
|
+
|
|
652
|
+
_DATETIME_MILLISECOND_ARGS = value_args_model([
|
|
653
|
+
{'name': 'datetime', 'type': 'datetime'}
|
|
654
|
+
])
|
|
655
|
+
|
|
656
|
+
|
|
657
|
+
# $function: datetimeMinute
|
|
658
|
+
# $group: datetime
|
|
659
|
+
# $doc: Get the minute of a datetime
|
|
660
|
+
# $arg datetime: The datetime
|
|
661
|
+
# $return: The minute
|
|
662
|
+
def _datetime_minute(args, unused_options):
|
|
663
|
+
datetime_, = value_args_validate(_DATETIME_MINUTE_ARGS, args)
|
|
664
|
+
return value_normalize_datetime(datetime_).minute
|
|
665
|
+
|
|
666
|
+
_DATETIME_MINUTE_ARGS = value_args_model([
|
|
667
|
+
{'name': 'datetime', 'type': 'datetime'}
|
|
668
|
+
])
|
|
669
|
+
|
|
670
|
+
|
|
671
|
+
# $function: datetimeMonth
|
|
672
|
+
# $group: datetime
|
|
673
|
+
# $doc: Get the month (1-12) of a datetime
|
|
674
|
+
# $arg datetime: The datetime
|
|
675
|
+
# $return: The month
|
|
676
|
+
def _datetime_month(args, unused_options):
|
|
677
|
+
datetime_, = value_args_validate(_DATETIME_MONTH_ARGS, args)
|
|
678
|
+
return value_normalize_datetime(datetime_).month
|
|
679
|
+
|
|
680
|
+
_DATETIME_MONTH_ARGS = value_args_model([
|
|
681
|
+
{'name': 'datetime', 'type': 'datetime'}
|
|
682
|
+
])
|
|
683
|
+
|
|
684
|
+
|
|
685
|
+
# $function: datetimeNew
|
|
686
|
+
# $group: datetime
|
|
687
|
+
# $doc: Create a new datetime
|
|
688
|
+
# $arg year: The full year
|
|
689
|
+
# $arg month: The month (1-12)
|
|
690
|
+
# $arg day: The day of the month
|
|
691
|
+
# $arg hour: Optional (default is 0). The hour (0-23).
|
|
692
|
+
# $arg minute: Optional (default is 0). The minute.
|
|
693
|
+
# $arg second: Optional (default is 0). The second.
|
|
694
|
+
# $arg millisecond: Optional (default is 0). The millisecond.
|
|
695
|
+
# $return: The new datetime
|
|
696
|
+
def _datetime_new(args, unused_options):
|
|
697
|
+
year, month, day, hour, minute, second, millisecond = value_args_validate(_DATETIME_NEW_ARGS, args)
|
|
698
|
+
|
|
699
|
+
# Adjust millisecond
|
|
700
|
+
if millisecond < 0 or millisecond >= 1000:
|
|
701
|
+
extra_seconds = millisecond // 1000
|
|
702
|
+
millisecond -= extra_seconds * 1000
|
|
703
|
+
second += extra_seconds
|
|
704
|
+
|
|
705
|
+
# Adjust seconds
|
|
706
|
+
if second < 0 or second >= 60:
|
|
707
|
+
extra_minutes = second // 60
|
|
708
|
+
second -= extra_minutes * 60
|
|
709
|
+
minute += extra_minutes
|
|
710
|
+
|
|
711
|
+
# Adjust minutes
|
|
712
|
+
if minute < 0 or minute >= 60:
|
|
713
|
+
extra_hours = minute // 60
|
|
714
|
+
minute -= extra_hours * 60
|
|
715
|
+
hour += extra_hours
|
|
716
|
+
|
|
717
|
+
# Adjust hours
|
|
718
|
+
if hour < 0 or hour >= 24:
|
|
719
|
+
extra_days = hour // 24
|
|
720
|
+
hour -= extra_days * 24
|
|
721
|
+
day += extra_days
|
|
722
|
+
|
|
723
|
+
# Adjust month
|
|
724
|
+
if month < 1 or month > 12:
|
|
725
|
+
extra_years = (month - 1) // 12
|
|
726
|
+
month -= extra_years * 12
|
|
727
|
+
year += extra_years
|
|
728
|
+
|
|
729
|
+
# Adjust day
|
|
730
|
+
if day < 1:
|
|
731
|
+
while day < 1:
|
|
732
|
+
year = year if month != 1 else year - 1
|
|
733
|
+
month = month - 1 if month != 1 else 12
|
|
734
|
+
_, month_days = calendar.monthrange(int(year), int(month))
|
|
735
|
+
day += month_days
|
|
736
|
+
elif day > 28:
|
|
737
|
+
_, month_days = calendar.monthrange(int(year), int(month))
|
|
738
|
+
while day > month_days:
|
|
739
|
+
day -= month_days
|
|
740
|
+
year = year if month != 12 else year + 1
|
|
741
|
+
month = month + 1 if month != 12 else 1
|
|
742
|
+
_, month_days = calendar.monthrange(int(year), int(month))
|
|
743
|
+
|
|
744
|
+
# Return the datetime
|
|
745
|
+
return datetime.datetime(int(year), int(month), int(day), int(hour), int(minute), int(second), int(millisecond) * 1000)
|
|
746
|
+
|
|
747
|
+
_DATETIME_NEW_ARGS = value_args_model([
|
|
748
|
+
{'name': 'year', 'type': 'number', 'integer': True, 'gte': 100},
|
|
749
|
+
{'name': 'month', 'type': 'number', 'integer': True},
|
|
750
|
+
{'name': 'day', 'type': 'number', 'integer': True, 'gte': -10000, 'lte': 10000},
|
|
751
|
+
{'name': 'hour', 'type': 'number', 'default': 0, 'integer': True},
|
|
752
|
+
{'name': 'minute', 'type': 'number', 'default': 0, 'integer': True},
|
|
753
|
+
{'name': 'second', 'type': 'number', 'default': 0, 'integer': True},
|
|
754
|
+
{'name': 'millisecond', 'type': 'number', 'default': 0, 'integer': True}
|
|
755
|
+
])
|
|
756
|
+
|
|
757
|
+
|
|
758
|
+
# $function: datetimeNow
|
|
759
|
+
# $group: datetime
|
|
760
|
+
# $doc: Get the current datetime
|
|
761
|
+
# $return: The current datetime
|
|
762
|
+
def _datetime_now(unused_args, unused_options):
|
|
763
|
+
return datetime.datetime.now()
|
|
764
|
+
|
|
765
|
+
|
|
766
|
+
# $function: datetimeSecond
|
|
767
|
+
# $group: datetime
|
|
768
|
+
# $doc: Get the second of a datetime
|
|
769
|
+
# $arg datetime: The datetime
|
|
770
|
+
# $return: The second
|
|
771
|
+
def _datetime_second(args, unused_options):
|
|
772
|
+
datetime_, = value_args_validate(_DATETIME_SECOND_ARGS, args)
|
|
773
|
+
return value_normalize_datetime(datetime_).second
|
|
774
|
+
|
|
775
|
+
_DATETIME_SECOND_ARGS = value_args_model([
|
|
776
|
+
{'name': 'datetime', 'type': 'datetime'}
|
|
777
|
+
])
|
|
778
|
+
|
|
779
|
+
|
|
780
|
+
# $function: datetimeToday
|
|
781
|
+
# $group: datetime
|
|
782
|
+
# $doc: Get today's datetime
|
|
783
|
+
# $return: Today's datetime
|
|
784
|
+
def _datetime_today(unused_args, unused_options):
|
|
785
|
+
today = datetime.date.today()
|
|
786
|
+
return datetime.datetime(today.year, today.month, today.day)
|
|
787
|
+
|
|
788
|
+
|
|
789
|
+
# $function: datetimeYear
|
|
790
|
+
# $group: datetime
|
|
791
|
+
# $doc: Get the full year of a datetime
|
|
792
|
+
# $arg datetime: The datetime
|
|
793
|
+
# $return: The full year
|
|
794
|
+
def _datetime_year(args, unused_options):
|
|
795
|
+
datetime_, = value_args_validate(_DATETIME_YEAR_ARGS, args)
|
|
796
|
+
return value_normalize_datetime(datetime_).year
|
|
797
|
+
|
|
798
|
+
_DATETIME_YEAR_ARGS = value_args_model([
|
|
799
|
+
{'name': 'datetime', 'type': 'datetime'}
|
|
800
|
+
])
|
|
801
|
+
|
|
802
|
+
|
|
803
|
+
#
|
|
804
|
+
# JSON functions
|
|
805
|
+
#
|
|
806
|
+
|
|
807
|
+
|
|
808
|
+
# $function: jsonParse
|
|
809
|
+
# $group: json
|
|
810
|
+
# $doc: Convert a JSON string to an object
|
|
811
|
+
# $arg string: The JSON string
|
|
812
|
+
# $return: The object
|
|
813
|
+
def _json_parse(args, unused_options):
|
|
814
|
+
string, = value_args_validate(_JSON_PARSE_ARGS, args)
|
|
815
|
+
return json.loads(string)
|
|
816
|
+
|
|
817
|
+
_JSON_PARSE_ARGS = value_args_model([
|
|
818
|
+
{'name': 'string', 'type': 'string'}
|
|
819
|
+
])
|
|
820
|
+
|
|
821
|
+
|
|
822
|
+
# $function: jsonStringify
|
|
823
|
+
# $group: json
|
|
824
|
+
# $doc: Convert an object to a JSON string
|
|
825
|
+
# $arg value: The object
|
|
826
|
+
# $arg indent: Optional (default is null). The indentation number.
|
|
827
|
+
# $return: The JSON string
|
|
828
|
+
def _json_stringify(args, unused_options):
|
|
829
|
+
value, indent = value_args_validate(_JSON_STRINGIFY_ARGS, args)
|
|
830
|
+
return value_json(value, int(indent) if indent is not None else None)
|
|
831
|
+
|
|
832
|
+
_JSON_STRINGIFY_ARGS = value_args_model([
|
|
833
|
+
{'name': 'value'},
|
|
834
|
+
{'name': 'indent', 'type': 'number', 'nullable': True, 'integer': True, 'gte': 1}
|
|
835
|
+
])
|
|
836
|
+
|
|
837
|
+
|
|
838
|
+
#
|
|
839
|
+
# Math functions
|
|
840
|
+
#
|
|
841
|
+
|
|
842
|
+
|
|
843
|
+
# $function: mathAbs
|
|
844
|
+
# $group: math
|
|
845
|
+
# $doc: Compute the absolute value of a number
|
|
846
|
+
# $arg x: The number
|
|
847
|
+
# $return: The absolute value of the number
|
|
848
|
+
def _math_abs(args, unused_options):
|
|
849
|
+
x, = value_args_validate(_MATH_ABS_ARGS, args)
|
|
850
|
+
return abs(x)
|
|
851
|
+
|
|
852
|
+
_MATH_ABS_ARGS = value_args_model([
|
|
853
|
+
{'name': 'x', 'type': 'number'}
|
|
854
|
+
])
|
|
855
|
+
|
|
856
|
+
|
|
857
|
+
# $function: mathAcos
|
|
858
|
+
# $group: math
|
|
859
|
+
# $doc: Compute the arccosine, in radians, of a number
|
|
860
|
+
# $arg x: The number
|
|
861
|
+
# $return: The arccosine, in radians, of the number
|
|
862
|
+
def _math_acos(args, unused_options):
|
|
863
|
+
x, = value_args_validate(_MATH_ACOS_ARGS, args)
|
|
864
|
+
return math.acos(x)
|
|
865
|
+
|
|
866
|
+
_MATH_ACOS_ARGS = value_args_model([
|
|
867
|
+
{'name': 'x', 'type': 'number'}
|
|
868
|
+
])
|
|
869
|
+
|
|
870
|
+
|
|
871
|
+
# $function: mathAsin
|
|
872
|
+
# $group: math
|
|
873
|
+
# $doc: Compute the arcsine, in radians, of a number
|
|
874
|
+
# $arg x: The number
|
|
875
|
+
# $return: The arcsine, in radians, of the number
|
|
876
|
+
def _math_asin(args, unused_options):
|
|
877
|
+
x, = value_args_validate(_MATH_ASIN_ARGS, args)
|
|
878
|
+
return math.asin(x)
|
|
879
|
+
|
|
880
|
+
_MATH_ASIN_ARGS = value_args_model([
|
|
881
|
+
{'name': 'x', 'type': 'number'}
|
|
882
|
+
])
|
|
883
|
+
|
|
884
|
+
|
|
885
|
+
# $function: mathAtan
|
|
886
|
+
# $group: math
|
|
887
|
+
# $doc: Compute the arctangent, in radians, of a number
|
|
888
|
+
# $arg x: The number
|
|
889
|
+
# $return: The arctangent, in radians, of the number
|
|
890
|
+
def _math_atan(args, unused_options):
|
|
891
|
+
x, = value_args_validate(_MATH_ATAN_ARGS, args)
|
|
892
|
+
return math.atan(x)
|
|
893
|
+
|
|
894
|
+
_MATH_ATAN_ARGS = value_args_model([
|
|
895
|
+
{'name': 'x', 'type': 'number'}
|
|
896
|
+
])
|
|
897
|
+
|
|
898
|
+
|
|
899
|
+
# $function: mathAtan2
|
|
900
|
+
# $group: math
|
|
901
|
+
# $doc: Compute the angle, in radians, between (0, 0) and a point
|
|
902
|
+
# $arg y: The Y-coordinate of the point
|
|
903
|
+
# $arg x: The X-coordinate of the point
|
|
904
|
+
# $return: The angle, in radians
|
|
905
|
+
def _math_atan2(args, unused_options):
|
|
906
|
+
y, x = value_args_validate(_MATH_ATAN2_ARGS, args)
|
|
907
|
+
return math.atan2(y, x)
|
|
908
|
+
|
|
909
|
+
_MATH_ATAN2_ARGS = value_args_model([
|
|
910
|
+
{'name': 'y', 'type': 'number'},
|
|
911
|
+
{'name': 'x', 'type': 'number'}
|
|
912
|
+
])
|
|
913
|
+
|
|
914
|
+
|
|
915
|
+
# $function: mathCeil
|
|
916
|
+
# $group: math
|
|
917
|
+
# $doc: Compute the ceiling of a number (round up to the next highest integer)
|
|
918
|
+
# $arg x: The number
|
|
919
|
+
# $return: The ceiling of the number
|
|
920
|
+
def _math_ceil(args, unused_options):
|
|
921
|
+
x, = value_args_validate(_MATH_CEIL_ARGS, args)
|
|
922
|
+
return math.ceil(x)
|
|
923
|
+
|
|
924
|
+
_MATH_CEIL_ARGS = value_args_model([
|
|
925
|
+
{'name': 'x', 'type': 'number'}
|
|
926
|
+
])
|
|
927
|
+
|
|
928
|
+
|
|
929
|
+
# $function: mathCos
|
|
930
|
+
# $group: math
|
|
931
|
+
# $doc: Compute the cosine of an angle, in radians
|
|
932
|
+
# $arg x: The angle, in radians
|
|
933
|
+
# $return: The cosine of the angle
|
|
934
|
+
def _math_cos(args, unused_options):
|
|
935
|
+
x, = value_args_validate(_MATH_COS_ARGS, args)
|
|
936
|
+
return math.cos(x)
|
|
937
|
+
|
|
938
|
+
_MATH_COS_ARGS = value_args_model([
|
|
939
|
+
{'name': 'x', 'type': 'number'}
|
|
940
|
+
])
|
|
941
|
+
|
|
942
|
+
|
|
943
|
+
# $function: mathFloor
|
|
944
|
+
# $group: math
|
|
945
|
+
# $doc: Compute the floor of a number (round down to the next lowest integer)
|
|
946
|
+
# $arg x: The number
|
|
947
|
+
# $return: The floor of the number
|
|
948
|
+
def _math_floor(args, unused_options):
|
|
949
|
+
x, = value_args_validate(_MATH_FLOOR_ARGS, args)
|
|
950
|
+
return math.floor(x)
|
|
951
|
+
|
|
952
|
+
_MATH_FLOOR_ARGS = value_args_model([
|
|
953
|
+
{'name': 'x', 'type': 'number'}
|
|
954
|
+
])
|
|
955
|
+
|
|
956
|
+
|
|
957
|
+
# $function: mathLn
|
|
958
|
+
# $group: math
|
|
959
|
+
# $doc: Compute the natural logarithm (base e) of a number
|
|
960
|
+
# $arg x: The number
|
|
961
|
+
# $return: The natural logarithm of the number
|
|
962
|
+
def _math_ln(args, unused_options):
|
|
963
|
+
x, = value_args_validate(_MATH_LN_ARGS, args)
|
|
964
|
+
return math.log(x)
|
|
965
|
+
|
|
966
|
+
_MATH_LN_ARGS = value_args_model([
|
|
967
|
+
{'name': 'x', 'type': 'number', 'gt': 0}
|
|
968
|
+
])
|
|
969
|
+
|
|
970
|
+
|
|
971
|
+
# $function: mathLog
|
|
972
|
+
# $group: math
|
|
973
|
+
# $doc: Compute the logarithm (base 10) of a number
|
|
974
|
+
# $arg x: The number
|
|
975
|
+
# $arg base: Optional (default is 10). The logarithm base.
|
|
976
|
+
# $return: The logarithm of the number
|
|
977
|
+
def _math_log(args, unused_options):
|
|
978
|
+
x, base = value_args_validate(_MATH_LOG_ARGS, args)
|
|
979
|
+
if base == 1:
|
|
980
|
+
raise ValueArgsError('base', base)
|
|
981
|
+
|
|
982
|
+
return math.log(x, base)
|
|
983
|
+
|
|
984
|
+
_MATH_LOG_ARGS = value_args_model([
|
|
985
|
+
{'name': 'x', 'type': 'number', 'gt': 0},
|
|
986
|
+
{'name': 'base', 'type': 'number', 'default': 10, 'gt': 0}
|
|
987
|
+
])
|
|
988
|
+
|
|
989
|
+
|
|
990
|
+
# $function: mathMax
|
|
991
|
+
# $group: math
|
|
992
|
+
# $doc: Compute the maximum value
|
|
993
|
+
# $arg values...: The values
|
|
994
|
+
# $return: The maximum value
|
|
995
|
+
def _math_max(values, unused_options):
|
|
996
|
+
result = None
|
|
997
|
+
is_first = True
|
|
998
|
+
for value in values:
|
|
999
|
+
if is_first:
|
|
1000
|
+
result = value
|
|
1001
|
+
is_first = False
|
|
1002
|
+
elif value_compare(value, result) > 0:
|
|
1003
|
+
result = value
|
|
1004
|
+
return result
|
|
1005
|
+
|
|
1006
|
+
|
|
1007
|
+
# $function: mathMin
|
|
1008
|
+
# $group: math
|
|
1009
|
+
# $doc: Compute the minimum value
|
|
1010
|
+
# $arg values...: The values
|
|
1011
|
+
# $return: The minimum value
|
|
1012
|
+
def _math_min(values, unused_options):
|
|
1013
|
+
result = None
|
|
1014
|
+
is_first = True
|
|
1015
|
+
for value in values:
|
|
1016
|
+
if is_first:
|
|
1017
|
+
result = value
|
|
1018
|
+
is_first = False
|
|
1019
|
+
elif value_compare(value, result) < 0:
|
|
1020
|
+
result = value
|
|
1021
|
+
return result
|
|
1022
|
+
|
|
1023
|
+
|
|
1024
|
+
# $function: mathPi
|
|
1025
|
+
# $group: math
|
|
1026
|
+
# $doc: Return the number pi
|
|
1027
|
+
# $return: The number pi
|
|
1028
|
+
def _math_pi(unused_args, unused_options):
|
|
1029
|
+
return math.pi
|
|
1030
|
+
|
|
1031
|
+
|
|
1032
|
+
# $function: mathRandom
|
|
1033
|
+
# $group: math
|
|
1034
|
+
# $doc: Compute a random number between 0 and 1, inclusive
|
|
1035
|
+
# $return: A random number
|
|
1036
|
+
def _math_random(unused_args, unused_options):
|
|
1037
|
+
return random.random()
|
|
1038
|
+
|
|
1039
|
+
|
|
1040
|
+
# $function: mathRound
|
|
1041
|
+
# $group: math
|
|
1042
|
+
# $doc: Round a number to a certain number of decimal places
|
|
1043
|
+
# $arg x: The number
|
|
1044
|
+
# $arg digits: Optional (default is 0). The number of decimal digits to round to.
|
|
1045
|
+
# $return: The rounded number
|
|
1046
|
+
def _math_round(args, unused_options):
|
|
1047
|
+
x, digits = value_args_validate(_MATH_ROUND_ARGS, args)
|
|
1048
|
+
return value_round_number(x, digits)
|
|
1049
|
+
|
|
1050
|
+
_MATH_ROUND_ARGS = value_args_model([
|
|
1051
|
+
{'name': 'x', 'type': 'number'},
|
|
1052
|
+
{'name': 'digits', 'type': 'number', 'default': 0, 'integer': True, 'gte': 0}
|
|
1053
|
+
])
|
|
1054
|
+
|
|
1055
|
+
|
|
1056
|
+
# $function: mathSign
|
|
1057
|
+
# $group: math
|
|
1058
|
+
# $doc: Compute the sign of a number
|
|
1059
|
+
# $arg x: The number
|
|
1060
|
+
# $return: -1 for a negative number, 1 for a positive number, and 0 for zero
|
|
1061
|
+
def _math_sign(args, unused_options):
|
|
1062
|
+
x, = value_args_validate(_MATH_SIGN_ARGS, args)
|
|
1063
|
+
return -1 if x < 0 else (0 if x == 0 else 1)
|
|
1064
|
+
|
|
1065
|
+
_MATH_SIGN_ARGS = value_args_model([
|
|
1066
|
+
{'name': 'x', 'type': 'number'}
|
|
1067
|
+
])
|
|
1068
|
+
|
|
1069
|
+
|
|
1070
|
+
# $function: mathSin
|
|
1071
|
+
# $group: math
|
|
1072
|
+
# $doc: Compute the sine of an angle, in radians
|
|
1073
|
+
# $arg x: The angle, in radians
|
|
1074
|
+
# $return: The sine of the angle
|
|
1075
|
+
def _math_sin(args, unused_options):
|
|
1076
|
+
x, = value_args_validate(_MATH_SIN_ARGS, args)
|
|
1077
|
+
return math.sin(x)
|
|
1078
|
+
|
|
1079
|
+
_MATH_SIN_ARGS = value_args_model([
|
|
1080
|
+
{'name': 'x', 'type': 'number'}
|
|
1081
|
+
])
|
|
1082
|
+
|
|
1083
|
+
|
|
1084
|
+
# $function: mathSqrt
|
|
1085
|
+
# $group: math
|
|
1086
|
+
# $doc: Compute the square root of a number
|
|
1087
|
+
# $arg x: The number
|
|
1088
|
+
# $return: The square root of the number
|
|
1089
|
+
def _math_sqrt(args, unused_options):
|
|
1090
|
+
x, = value_args_validate(_MATH_SQRT_ARGS, args)
|
|
1091
|
+
return math.sqrt(x)
|
|
1092
|
+
|
|
1093
|
+
_MATH_SQRT_ARGS = value_args_model([
|
|
1094
|
+
{'name': 'x', 'type': 'number', 'gte': 0}
|
|
1095
|
+
])
|
|
1096
|
+
|
|
1097
|
+
|
|
1098
|
+
# $function: mathTan
|
|
1099
|
+
# $group: math
|
|
1100
|
+
# $doc: Compute the tangent of an angle, in radians
|
|
1101
|
+
# $arg x: The angle, in radians
|
|
1102
|
+
# $return: The tangent of the angle
|
|
1103
|
+
def _math_tan(args, unused_options):
|
|
1104
|
+
x, = value_args_validate(_MATH_TAN_ARGS, args)
|
|
1105
|
+
return math.tan(x)
|
|
1106
|
+
|
|
1107
|
+
_MATH_TAN_ARGS = value_args_model([
|
|
1108
|
+
{'name': 'x', 'type': 'number'}
|
|
1109
|
+
])
|
|
1110
|
+
|
|
1111
|
+
|
|
1112
|
+
#
|
|
1113
|
+
# Number functions
|
|
1114
|
+
#
|
|
1115
|
+
|
|
1116
|
+
|
|
1117
|
+
# $function: numberParseFloat
|
|
1118
|
+
# $group: number
|
|
1119
|
+
# $doc: Parse a string as a floating point number
|
|
1120
|
+
# $arg string: The string
|
|
1121
|
+
# $return: The number
|
|
1122
|
+
def _number_parse_float(args, unused_options):
|
|
1123
|
+
string, = value_args_validate(_NUMBER_PARSE_FLOAT_ARGS, args)
|
|
1124
|
+
return value_parse_number(string)
|
|
1125
|
+
|
|
1126
|
+
_NUMBER_PARSE_FLOAT_ARGS = value_args_model([
|
|
1127
|
+
{'name': 'string', 'type': 'string'}
|
|
1128
|
+
])
|
|
1129
|
+
|
|
1130
|
+
|
|
1131
|
+
# $function: numberParseInt
|
|
1132
|
+
# $group: number
|
|
1133
|
+
# $doc: Parse a string as an integer
|
|
1134
|
+
# $arg string: The string
|
|
1135
|
+
# $arg radix: Optional (default is 10). The number base.
|
|
1136
|
+
# $return: The integer
|
|
1137
|
+
def _number_parse_int(args, unused_options):
|
|
1138
|
+
string, radix = value_args_validate(_NUMBER_PARSE_INT_ARGS, args)
|
|
1139
|
+
return value_parse_integer(string, int(radix))
|
|
1140
|
+
|
|
1141
|
+
_NUMBER_PARSE_INT_ARGS = value_args_model([
|
|
1142
|
+
{'name': 'string', 'type': 'string'},
|
|
1143
|
+
{'name': 'radix', 'type': 'number', 'default': 10, 'integer': True, 'gte': 2, 'lte': 36}
|
|
1144
|
+
])
|
|
1145
|
+
|
|
1146
|
+
|
|
1147
|
+
# $function: numberToFixed
|
|
1148
|
+
# $group: number
|
|
1149
|
+
# $doc: Format a number using fixed-point notation
|
|
1150
|
+
# $arg x: The number
|
|
1151
|
+
# $arg digits: Optional (default is 2). The number of digits to appear after the decimal point.
|
|
1152
|
+
# $arg trim: Optional (default is false). If true, trim trailing zeroes and decimal point.
|
|
1153
|
+
# $return: The fixed-point notation string
|
|
1154
|
+
def _number_to_fixed(args, unused_options):
|
|
1155
|
+
x, digits, trim = value_args_validate(_NUMBER_TO_FIXED_ARGS, args)
|
|
1156
|
+
result = f'{value_round_number(x, digits):.{int(digits)}f}'
|
|
1157
|
+
if trim:
|
|
1158
|
+
return R_NUMBER_CLEANUP.sub('', result)
|
|
1159
|
+
return result
|
|
1160
|
+
|
|
1161
|
+
_NUMBER_TO_FIXED_ARGS = value_args_model([
|
|
1162
|
+
{'name': 'x', 'type': 'number'},
|
|
1163
|
+
{'name': 'digits', 'type': 'number', 'default': 2, 'integer': True, 'gte': 0},
|
|
1164
|
+
{'name': 'trim', 'type': 'boolean', 'default': False}
|
|
1165
|
+
])
|
|
1166
|
+
|
|
1167
|
+
|
|
1168
|
+
#
|
|
1169
|
+
# Object functions
|
|
1170
|
+
#
|
|
1171
|
+
|
|
1172
|
+
|
|
1173
|
+
# $function: objectAssign
|
|
1174
|
+
# $group: object
|
|
1175
|
+
# $doc: Assign the keys/values of one object to another
|
|
1176
|
+
# $arg object: The object to assign to
|
|
1177
|
+
# $arg object2: The object to assign
|
|
1178
|
+
# $return: The updated object
|
|
1179
|
+
def _object_assign(args, unused_options):
|
|
1180
|
+
object_, object2 = value_args_validate(_OBJECT_ASSIGN_ARGS, args)
|
|
1181
|
+
object_.update(object2)
|
|
1182
|
+
return object_
|
|
1183
|
+
|
|
1184
|
+
_OBJECT_ASSIGN_ARGS = value_args_model([
|
|
1185
|
+
{'name': 'object', 'type': 'object'},
|
|
1186
|
+
{'name': 'object2', 'type': 'object'}
|
|
1187
|
+
])
|
|
1188
|
+
|
|
1189
|
+
|
|
1190
|
+
# $function: objectCopy
|
|
1191
|
+
# $group: object
|
|
1192
|
+
# $doc: Create a copy of an object
|
|
1193
|
+
# $arg object: The object to copy
|
|
1194
|
+
# $return: The object copy
|
|
1195
|
+
def _object_copy(args, unused_options):
|
|
1196
|
+
object_, = value_args_validate(_OBJECT_COPY_ARGS, args)
|
|
1197
|
+
return dict(object_)
|
|
1198
|
+
|
|
1199
|
+
_OBJECT_COPY_ARGS = value_args_model([
|
|
1200
|
+
{'name': 'object', 'type': 'object'}
|
|
1201
|
+
])
|
|
1202
|
+
|
|
1203
|
+
|
|
1204
|
+
# $function: objectDelete
|
|
1205
|
+
# $group: object
|
|
1206
|
+
# $doc: Delete an object key
|
|
1207
|
+
# $arg object: The object
|
|
1208
|
+
# $arg key: The key to delete
|
|
1209
|
+
def _object_delete(args, unused_options):
|
|
1210
|
+
object_, key = value_args_validate(_OBJECT_DELETE_ARGS, args)
|
|
1211
|
+
if key in object_:
|
|
1212
|
+
del object_[key]
|
|
1213
|
+
|
|
1214
|
+
_OBJECT_DELETE_ARGS = value_args_model([
|
|
1215
|
+
{'name': 'object', 'type': 'object'},
|
|
1216
|
+
{'name': 'key', 'type': 'string'}
|
|
1217
|
+
])
|
|
1218
|
+
|
|
1219
|
+
|
|
1220
|
+
# $function: objectGet
|
|
1221
|
+
# $group: object
|
|
1222
|
+
# $doc: Get an object key's value
|
|
1223
|
+
# $arg object: The object
|
|
1224
|
+
# $arg key: The key
|
|
1225
|
+
# $arg defaultValue: The default value (optional)
|
|
1226
|
+
# $return: The value or null if the key does not exist
|
|
1227
|
+
def _object_get(args, unused_options):
|
|
1228
|
+
default_value_arg = args[2] if len(args) >= 3 else None
|
|
1229
|
+
object_, key, default_value = value_args_validate(_OBJECT_GET_ARGS, args, default_value_arg)
|
|
1230
|
+
return object_.get(key, default_value)
|
|
1231
|
+
|
|
1232
|
+
_OBJECT_GET_ARGS = value_args_model([
|
|
1233
|
+
{'name': 'object', 'type': 'object'},
|
|
1234
|
+
{'name': 'key', 'type': 'string'},
|
|
1235
|
+
{'name': 'defaultValue'}
|
|
1236
|
+
])
|
|
1237
|
+
|
|
1238
|
+
|
|
1239
|
+
# $function: objectHas
|
|
1240
|
+
# $group: object
|
|
1241
|
+
# $doc: Test if an object contains a key
|
|
1242
|
+
# $arg object: The object
|
|
1243
|
+
# $arg key: The key
|
|
1244
|
+
# $return: true if the object contains the key, false otherwise
|
|
1245
|
+
def _object_has(args, unused_options):
|
|
1246
|
+
object_, key = value_args_validate(_OBJECT_HAS_ARGS, args, False)
|
|
1247
|
+
return key in object_
|
|
1248
|
+
|
|
1249
|
+
_OBJECT_HAS_ARGS = value_args_model([
|
|
1250
|
+
{'name': 'object', 'type': 'object'},
|
|
1251
|
+
{'name': 'key', 'type': 'string'}
|
|
1252
|
+
])
|
|
1253
|
+
|
|
1254
|
+
|
|
1255
|
+
# $function: objectKeys
|
|
1256
|
+
# $group: object
|
|
1257
|
+
# $doc: Get an object's keys
|
|
1258
|
+
# $arg object: The object
|
|
1259
|
+
# $return: The array of keys
|
|
1260
|
+
def _object_keys(args, unused_options):
|
|
1261
|
+
object_, = value_args_validate(_OBJECT_KEYS_ARGS, args)
|
|
1262
|
+
return list(object_.keys())
|
|
1263
|
+
|
|
1264
|
+
_OBJECT_KEYS_ARGS = value_args_model([
|
|
1265
|
+
{'name': 'object', 'type': 'object'}
|
|
1266
|
+
])
|
|
1267
|
+
|
|
1268
|
+
|
|
1269
|
+
# $function: objectNew
|
|
1270
|
+
# $group: object
|
|
1271
|
+
# $doc: Create a new object
|
|
1272
|
+
# $arg keyValues...: The object's initial key and value pairs
|
|
1273
|
+
# $return: The new object
|
|
1274
|
+
def _object_new(args, unused_options):
|
|
1275
|
+
object_ = {}
|
|
1276
|
+
for ix in range(0, len(args), 2):
|
|
1277
|
+
key = args[ix]
|
|
1278
|
+
value = args[ix + 1] if ix + 1 < len(args) else None
|
|
1279
|
+
if value_type(key) != 'string':
|
|
1280
|
+
raise ValueArgsError('keyValues', key)
|
|
1281
|
+
object_[key] = value
|
|
1282
|
+
return object_
|
|
1283
|
+
|
|
1284
|
+
|
|
1285
|
+
# $function: objectSet
|
|
1286
|
+
# $group: object
|
|
1287
|
+
# $doc: Set an object key's value
|
|
1288
|
+
# $arg object: The object
|
|
1289
|
+
# $arg key: The key
|
|
1290
|
+
# $arg value: The value to set
|
|
1291
|
+
# $return: The value to set
|
|
1292
|
+
def _object_set(args, unused_options):
|
|
1293
|
+
object_, key, value = value_args_validate(_OBJECT_SET_ARGS, args)
|
|
1294
|
+
object_[key] = value
|
|
1295
|
+
return value
|
|
1296
|
+
|
|
1297
|
+
_OBJECT_SET_ARGS = value_args_model([
|
|
1298
|
+
{'name': 'object', 'type': 'object'},
|
|
1299
|
+
{'name': 'key', 'type': 'string'},
|
|
1300
|
+
{'name': 'value'}
|
|
1301
|
+
])
|
|
1302
|
+
|
|
1303
|
+
|
|
1304
|
+
#
|
|
1305
|
+
# Regex functions
|
|
1306
|
+
#
|
|
1307
|
+
|
|
1308
|
+
|
|
1309
|
+
# $function: regexEscape
|
|
1310
|
+
# $group: regex
|
|
1311
|
+
# $doc: Escape a string for use in a regular expression
|
|
1312
|
+
# $arg string: The string to escape
|
|
1313
|
+
# $return: The escaped string
|
|
1314
|
+
def _regex_escape(args, unused_options):
|
|
1315
|
+
string, = value_args_validate(_REGEX_ESCAPE_ARGS, args)
|
|
1316
|
+
return re.escape(string)
|
|
1317
|
+
|
|
1318
|
+
_REGEX_ESCAPE_ARGS = value_args_model([
|
|
1319
|
+
{'name': 'string', 'type': 'string'}
|
|
1320
|
+
])
|
|
1321
|
+
|
|
1322
|
+
|
|
1323
|
+
# $function: regexMatch
|
|
1324
|
+
# $group: regex
|
|
1325
|
+
# $doc: Find the first match of a regular expression in a string
|
|
1326
|
+
# $arg regex: The regular expression
|
|
1327
|
+
# $arg string: The string
|
|
1328
|
+
# $return: The [match object](https://craigahobbs.github.io/bare-script-py/library/model.html#var.vName='RegexMatch'),
|
|
1329
|
+
# $return: or null if no matches are found
|
|
1330
|
+
def _regex_match(args, unused_options):
|
|
1331
|
+
regex, string = value_args_validate(_REGEX_MATCH_ARGS, args)
|
|
1332
|
+
match = regex.search(string)
|
|
1333
|
+
return _regex_match_groups(match) if match is not None else None
|
|
1334
|
+
|
|
1335
|
+
_REGEX_MATCH_ARGS = value_args_model([
|
|
1336
|
+
{'name': 'regex', 'type': 'regex'},
|
|
1337
|
+
{'name': 'string', 'type': 'string'}
|
|
1338
|
+
])
|
|
1339
|
+
|
|
1340
|
+
|
|
1341
|
+
# $function: regexMatchAll
|
|
1342
|
+
# $group: regex
|
|
1343
|
+
# $doc: Find all matches of regular expression in a string
|
|
1344
|
+
# $arg regex: The regular expression
|
|
1345
|
+
# $arg string: The string
|
|
1346
|
+
# $return: The array of [match objects](https://craigahobbs.github.io/bare-script-py/library/model.html#var.vName='RegexMatch')
|
|
1347
|
+
def _regex_match_all(args, unused_options):
|
|
1348
|
+
regex, string = value_args_validate(_REGEX_MATCH_ALL_ARGS, args)
|
|
1349
|
+
return [_regex_match_groups(match) for match in regex.finditer(string)]
|
|
1350
|
+
|
|
1351
|
+
_REGEX_MATCH_ALL_ARGS = value_args_model([
|
|
1352
|
+
{'name': 'regex', 'type': 'regex'},
|
|
1353
|
+
{'name': 'string', 'type': 'string'}
|
|
1354
|
+
])
|
|
1355
|
+
|
|
1356
|
+
|
|
1357
|
+
# Helper function to create a match model from a metch object
|
|
1358
|
+
def _regex_match_groups(match):
|
|
1359
|
+
groups = {'0': match[0]}
|
|
1360
|
+
groups.update((f'{match_ix + 1}', match_text) for match_ix, match_text in enumerate(match.groups()))
|
|
1361
|
+
groups.update(match.groupdict())
|
|
1362
|
+
return {
|
|
1363
|
+
'index': match.start(),
|
|
1364
|
+
'input': match.string,
|
|
1365
|
+
'groups': groups
|
|
1366
|
+
}
|
|
1367
|
+
|
|
1368
|
+
|
|
1369
|
+
# The regex match model
|
|
1370
|
+
REGEX_MATCH_TYPES = parse_schema_markdown('''\
|
|
1371
|
+
group "RegexMatch"
|
|
1372
|
+
|
|
1373
|
+
|
|
1374
|
+
# A regex match model
|
|
1375
|
+
struct RegexMatch
|
|
1376
|
+
|
|
1377
|
+
# The zero-based index of the match in the input string
|
|
1378
|
+
int(>= 0) index
|
|
1379
|
+
|
|
1380
|
+
# The input string
|
|
1381
|
+
string input
|
|
1382
|
+
|
|
1383
|
+
# The matched groups. The "0" key is the full match text. Ordered (non-named) groups use keys "1", "2", and so on.
|
|
1384
|
+
string{} groups
|
|
1385
|
+
''')
|
|
1386
|
+
|
|
1387
|
+
|
|
1388
|
+
# $function: regexNew
|
|
1389
|
+
# $group: regex
|
|
1390
|
+
# $doc: Create a regular expression
|
|
1391
|
+
# pylint: disable-next=line-too-long
|
|
1392
|
+
# $arg pattern: The [regular expression pattern string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions#writing_a_regular_expression_pattern)
|
|
1393
|
+
# $arg flags: The regular expression flags. The string may contain the following characters:
|
|
1394
|
+
# $arg flags: - **i** - case-insensitive search
|
|
1395
|
+
# $arg flags: - **m** - multi-line search - "^" and "$" matches next to newline characters
|
|
1396
|
+
# $arg flags: - **s** - "." matches newline characters
|
|
1397
|
+
# $return: The regular expression or null if the pattern is invalid
|
|
1398
|
+
def _regex_new(args, unused_options):
|
|
1399
|
+
pattern, flags = value_args_validate(_REGEX_NEW_ARGS, args)
|
|
1400
|
+
|
|
1401
|
+
# Translate JavaScript named group syntax to Python
|
|
1402
|
+
pattern = _R_REGEX_NEW_NAMED.sub(r'(?P<\1>', pattern)
|
|
1403
|
+
|
|
1404
|
+
# Compute the flags mask
|
|
1405
|
+
flags_mask = 0
|
|
1406
|
+
if flags is not None:
|
|
1407
|
+
for flag in flags:
|
|
1408
|
+
if flag == 'i':
|
|
1409
|
+
flags_mask = flags_mask | re.I
|
|
1410
|
+
elif flag == 'm':
|
|
1411
|
+
flags_mask = flags_mask | re.M
|
|
1412
|
+
elif flag == 's':
|
|
1413
|
+
flags_mask = flags_mask | re.S
|
|
1414
|
+
else:
|
|
1415
|
+
return None
|
|
1416
|
+
|
|
1417
|
+
return re.compile(pattern, flags_mask)
|
|
1418
|
+
|
|
1419
|
+
_REGEX_NEW_ARGS = value_args_model([
|
|
1420
|
+
{'name': 'pattern', 'type': 'string'},
|
|
1421
|
+
{'name': 'flags', 'type': 'string', 'nullable': True}
|
|
1422
|
+
])
|
|
1423
|
+
|
|
1424
|
+
|
|
1425
|
+
_R_REGEX_NEW_NAMED = re.compile(r'\(\?<(\w+)>')
|
|
1426
|
+
|
|
1427
|
+
|
|
1428
|
+
# $function: regexReplace
|
|
1429
|
+
# $group: regex
|
|
1430
|
+
# $doc: Replace regular expression matches with a string
|
|
1431
|
+
# $arg regex: The replacement regular expression
|
|
1432
|
+
# $arg string: The string
|
|
1433
|
+
# $arg substr: The replacement string
|
|
1434
|
+
# $return: The updated string
|
|
1435
|
+
def _regex_replace(args, unused_options):
|
|
1436
|
+
regex, string, substr = value_args_validate(_REGEX_REPLACE_ARGS, args)
|
|
1437
|
+
|
|
1438
|
+
# Escape Python escapes
|
|
1439
|
+
substr = substr.replace('\\', '\\\\')
|
|
1440
|
+
|
|
1441
|
+
# Un-escape Javascript escapes
|
|
1442
|
+
substr = substr.replace('$$', '$')
|
|
1443
|
+
|
|
1444
|
+
# Translate JavaScript replacers to Python replacers
|
|
1445
|
+
substr = _R_REGEX_REPLACE_INDEX.sub(r'\\\1', substr)
|
|
1446
|
+
substr = _R_REGEX_REPLACE_NAMED.sub(r'\\g<\1>', substr)
|
|
1447
|
+
|
|
1448
|
+
return regex.sub(substr, string)
|
|
1449
|
+
|
|
1450
|
+
_REGEX_REPLACE_ARGS = value_args_model([
|
|
1451
|
+
{'name': 'regex', 'type': 'regex'},
|
|
1452
|
+
{'name': 'string', 'type': 'string'},
|
|
1453
|
+
{'name': 'substr', 'type': 'string'}
|
|
1454
|
+
])
|
|
1455
|
+
|
|
1456
|
+
|
|
1457
|
+
_R_REGEX_REPLACE_INDEX = re.compile(r'\$(\d+)')
|
|
1458
|
+
_R_REGEX_REPLACE_NAMED = re.compile(r'\$<(?P<name>[^>]+)>')
|
|
1459
|
+
|
|
1460
|
+
|
|
1461
|
+
# $function: regexSplit
|
|
1462
|
+
# $group: regex
|
|
1463
|
+
# $doc: Split a string with a regular expression
|
|
1464
|
+
# $arg regex: The regular expression
|
|
1465
|
+
# $arg string: The string
|
|
1466
|
+
# $return: The array of split parts
|
|
1467
|
+
def _regex_split(args, unused_options):
|
|
1468
|
+
regex, string = value_args_validate(_REGEX_SPLIT_ARGS, args)
|
|
1469
|
+
return regex.split(string)
|
|
1470
|
+
|
|
1471
|
+
_REGEX_SPLIT_ARGS = value_args_model([
|
|
1472
|
+
{'name': 'regex', 'type': 'regex'},
|
|
1473
|
+
{'name': 'string', 'type': 'string'}
|
|
1474
|
+
])
|
|
1475
|
+
|
|
1476
|
+
|
|
1477
|
+
#
|
|
1478
|
+
# Schema functions
|
|
1479
|
+
#
|
|
1480
|
+
|
|
1481
|
+
|
|
1482
|
+
# $function: schemaParse
|
|
1483
|
+
# $group: schema
|
|
1484
|
+
# $doc: Parse the [Schema Markdown](https://craigahobbs.github.io/schema-markdown-js/language/) text
|
|
1485
|
+
# $arg lines...: The [Schema Markdown](https://craigahobbs.github.io/schema-markdown-js/language/)
|
|
1486
|
+
# $arg lines...: text lines (may contain nested arrays of un-split lines)
|
|
1487
|
+
# $return: The schema's [type model](https://craigahobbs.github.io/schema-markdown-doc/doc/#var.vName='Types')
|
|
1488
|
+
def _schema_parse(args, unused_options):
|
|
1489
|
+
return parse_schema_markdown(args)
|
|
1490
|
+
|
|
1491
|
+
|
|
1492
|
+
# $function: schemaParseEx
|
|
1493
|
+
# $group: schema
|
|
1494
|
+
# $doc: Parse the [Schema Markdown](https://craigahobbs.github.io/schema-markdown-js/language/) text with options
|
|
1495
|
+
# $arg lines: The array of [Schema Markdown](https://craigahobbs.github.io/schema-markdown-js/language/)
|
|
1496
|
+
# $arg lines: text lines (may contain nested arrays of un-split lines)
|
|
1497
|
+
# $arg types: Optional. The [type model](https://craigahobbs.github.io/schema-markdown-doc/doc/#var.vName='Types').
|
|
1498
|
+
# $arg filename: Optional (default is ""). The file name.
|
|
1499
|
+
# $return: The schema's [type model](https://craigahobbs.github.io/schema-markdown-doc/doc/#var.vName='Types')
|
|
1500
|
+
def _schema_parse_ex(args, unused_options):
|
|
1501
|
+
lines, types, filename = value_args_validate(_SCHEMA_PARSE_EX_ARGS, args)
|
|
1502
|
+
lines_type = value_type(lines)
|
|
1503
|
+
types = types if types is not None else {}
|
|
1504
|
+
if lines_type not in ('array', 'string'):
|
|
1505
|
+
raise ValueArgsError('lines', lines)
|
|
1506
|
+
|
|
1507
|
+
return parse_schema_markdown(lines, types, filename)
|
|
1508
|
+
|
|
1509
|
+
_SCHEMA_PARSE_EX_ARGS = value_args_model([
|
|
1510
|
+
{'name': 'lines'},
|
|
1511
|
+
{'name': 'types', 'type': 'object', 'nullable': True},
|
|
1512
|
+
{'name': 'filename', 'type': 'string', 'default': ''}
|
|
1513
|
+
])
|
|
1514
|
+
|
|
1515
|
+
|
|
1516
|
+
# $function: schemaTypeModel
|
|
1517
|
+
# $group: schema
|
|
1518
|
+
# $doc: Get the [Schema Markdown Type Model](https://craigahobbs.github.io/schema-markdown-doc/doc/#var.vName='Types')
|
|
1519
|
+
# $return: The [Schema Markdown Type Model](https://craigahobbs.github.io/schema-markdown-doc/doc/#var.vName='Types')
|
|
1520
|
+
def _schema_type_model(unused_args, unused_options):
|
|
1521
|
+
return TYPE_MODEL
|
|
1522
|
+
|
|
1523
|
+
|
|
1524
|
+
# $function: schemaValidate
|
|
1525
|
+
# $group: schema
|
|
1526
|
+
# $doc: Validate an object to a schema type
|
|
1527
|
+
# $arg types: The [type model](https://craigahobbs.github.io/schema-markdown-doc/doc/#var.vName='Types')
|
|
1528
|
+
# $arg typeName: The type name
|
|
1529
|
+
# $arg value: The object to validate
|
|
1530
|
+
# $return: The validated object or null if validation fails
|
|
1531
|
+
def _schema_validate(args, unused_options):
|
|
1532
|
+
types, type_name, value = value_args_validate(_SCHEMA_VALIDATE_ARGS, args)
|
|
1533
|
+
validate_type_model(types)
|
|
1534
|
+
return validate_type(types, type_name, value)
|
|
1535
|
+
|
|
1536
|
+
_SCHEMA_VALIDATE_ARGS = value_args_model([
|
|
1537
|
+
{'name': 'types', 'type': 'object'},
|
|
1538
|
+
{'name': 'typeName', 'type': 'string'},
|
|
1539
|
+
{'name': 'value'}
|
|
1540
|
+
])
|
|
1541
|
+
|
|
1542
|
+
|
|
1543
|
+
# $function: schemaValidateTypeModel
|
|
1544
|
+
# $group: schema
|
|
1545
|
+
# $doc: Validate a [Schema Markdown Type Model](https://craigahobbs.github.io/schema-markdown-doc/doc/#var.vName='Types')
|
|
1546
|
+
# $arg types: The [type model](https://craigahobbs.github.io/schema-markdown-doc/doc/#var.vName='Types') to validate
|
|
1547
|
+
# $return: The validated [type model](https://craigahobbs.github.io/schema-markdown-doc/doc/#var.vName='Types')
|
|
1548
|
+
def _schema_validate_type_model(args, unused_options):
|
|
1549
|
+
types, = value_args_validate(_SCHEMA_VALIDATE_TYPE_MODEL_ARGS, args)
|
|
1550
|
+
return validate_type_model(types)
|
|
1551
|
+
|
|
1552
|
+
_SCHEMA_VALIDATE_TYPE_MODEL_ARGS = value_args_model([
|
|
1553
|
+
{'name': 'types', 'type': 'object'}
|
|
1554
|
+
])
|
|
1555
|
+
|
|
1556
|
+
|
|
1557
|
+
#
|
|
1558
|
+
# String functions
|
|
1559
|
+
#
|
|
1560
|
+
|
|
1561
|
+
|
|
1562
|
+
# $function: stringCharCodeAt
|
|
1563
|
+
# $group: string
|
|
1564
|
+
# $doc: Get a string index's character code
|
|
1565
|
+
# $arg string: The string
|
|
1566
|
+
# $arg index: The character index
|
|
1567
|
+
# $return: The character code
|
|
1568
|
+
def _string_char_code_at(args, unused_options):
|
|
1569
|
+
string, index = value_args_validate(_STRING_CHAR_CODE_AT_ARGS, args)
|
|
1570
|
+
if index >= len(string):
|
|
1571
|
+
raise ValueArgsError('index', index)
|
|
1572
|
+
|
|
1573
|
+
return ord(string[int(index)])
|
|
1574
|
+
|
|
1575
|
+
_STRING_CHAR_CODE_AT_ARGS = value_args_model([
|
|
1576
|
+
{'name': 'string', 'type': 'string'},
|
|
1577
|
+
{'name': 'index', 'type': 'number', 'integer': True, 'gte': 0}
|
|
1578
|
+
])
|
|
1579
|
+
|
|
1580
|
+
|
|
1581
|
+
# $function: stringEndsWith
|
|
1582
|
+
# $group: string
|
|
1583
|
+
# $doc: Determine if a string ends with a search string
|
|
1584
|
+
# $arg string: The string
|
|
1585
|
+
# $arg search: The search string
|
|
1586
|
+
# $return: true if the string ends with the search string, false otherwise
|
|
1587
|
+
def _string_ends_with(args, unused_options):
|
|
1588
|
+
string, search = value_args_validate(_STRING_ENDS_WITH_ARGS, args)
|
|
1589
|
+
return string.endswith(search)
|
|
1590
|
+
|
|
1591
|
+
_STRING_ENDS_WITH_ARGS = value_args_model([
|
|
1592
|
+
{'name': 'string', 'type': 'string'},
|
|
1593
|
+
{'name': 'search', 'type': 'string'}
|
|
1594
|
+
])
|
|
1595
|
+
|
|
1596
|
+
|
|
1597
|
+
# $function: stringFromCharCode
|
|
1598
|
+
# $group: string
|
|
1599
|
+
# $doc: Create a string of characters from character codes
|
|
1600
|
+
# $arg charCodes...: The character codes
|
|
1601
|
+
# $return: The string of characters
|
|
1602
|
+
def _string_from_char_code(char_codes, unused_options):
|
|
1603
|
+
for code in char_codes:
|
|
1604
|
+
if value_type(code) != 'number' or int(code) != code or code < 0:
|
|
1605
|
+
raise ValueArgsError('char_codes', code)
|
|
1606
|
+
|
|
1607
|
+
return ''.join(chr(int(code)) for code in char_codes)
|
|
1608
|
+
|
|
1609
|
+
|
|
1610
|
+
# $function: stringIndexOf
|
|
1611
|
+
# $group: string
|
|
1612
|
+
# $doc: Find the first index of a search string in a string
|
|
1613
|
+
# $arg string: The string
|
|
1614
|
+
# $arg search: The search string
|
|
1615
|
+
# $arg index: Optional (default is 0). The index at which to start the search.
|
|
1616
|
+
# $return: The first index of the search string; -1 if not found.
|
|
1617
|
+
def _string_index_of(args, unused_options):
|
|
1618
|
+
string, search, index = value_args_validate(_STRING_INDEX_OF_ARGS, args, -1)
|
|
1619
|
+
if index >= len(string):
|
|
1620
|
+
raise ValueArgsError('index', index, -1)
|
|
1621
|
+
|
|
1622
|
+
return string.find(search, int(index))
|
|
1623
|
+
|
|
1624
|
+
_STRING_INDEX_OF_ARGS = value_args_model([
|
|
1625
|
+
{'name': 'string', 'type': 'string'},
|
|
1626
|
+
{'name': 'search', 'type': 'string'},
|
|
1627
|
+
{'name': 'index', 'type': 'number', 'default': 0, 'integer': True, 'gte': 0}
|
|
1628
|
+
])
|
|
1629
|
+
|
|
1630
|
+
|
|
1631
|
+
# $function: stringLastIndexOf
|
|
1632
|
+
# $group: string
|
|
1633
|
+
# $doc: Find the last index of a search string in a string
|
|
1634
|
+
# $arg string: The string
|
|
1635
|
+
# $arg search: The search string
|
|
1636
|
+
# $arg index: Optional (default is the end of the string). The index at which to start the search.
|
|
1637
|
+
# $return: The last index of the search string; -1 if not found.
|
|
1638
|
+
def _string_last_index_of(args, unused_options):
|
|
1639
|
+
string, search, index = value_args_validate(_STRING_LAST_INDEX_OF_ARGS, args, -1)
|
|
1640
|
+
index = index if index is not None else len(string) - 1
|
|
1641
|
+
if index >= len(string):
|
|
1642
|
+
raise ValueArgsError('index', index, -1)
|
|
1643
|
+
|
|
1644
|
+
return string.rfind(search, 0, int(index) + len(search))
|
|
1645
|
+
|
|
1646
|
+
_STRING_LAST_INDEX_OF_ARGS = value_args_model([
|
|
1647
|
+
{'name': 'string', 'type': 'string'},
|
|
1648
|
+
{'name': 'search', 'type': 'string'},
|
|
1649
|
+
{'name': 'index', 'type': 'number', 'nullable': True, 'integer': True, 'gte': 0}
|
|
1650
|
+
])
|
|
1651
|
+
|
|
1652
|
+
|
|
1653
|
+
# $function: stringLength
|
|
1654
|
+
# $group: string
|
|
1655
|
+
# $doc: Get the length of a string
|
|
1656
|
+
# $arg string: The string
|
|
1657
|
+
# $return: The string's length; zero if not a string
|
|
1658
|
+
def _string_length(args, unused_options):
|
|
1659
|
+
string, = value_args_validate(_STRING_LENGTH_ARGS, args, 0)
|
|
1660
|
+
return len(string)
|
|
1661
|
+
|
|
1662
|
+
_STRING_LENGTH_ARGS = value_args_model([
|
|
1663
|
+
{'name': 'string', 'type': 'string'}
|
|
1664
|
+
])
|
|
1665
|
+
|
|
1666
|
+
|
|
1667
|
+
# $function: stringLower
|
|
1668
|
+
# $group: string
|
|
1669
|
+
# $doc: Convert a string to lower-case
|
|
1670
|
+
# $arg string: The string
|
|
1671
|
+
# $return: The lower-case string
|
|
1672
|
+
def _string_lower(args, unused_options):
|
|
1673
|
+
string, = value_args_validate(_STRING_LOWER_ARGS, args)
|
|
1674
|
+
return string.lower()
|
|
1675
|
+
|
|
1676
|
+
_STRING_LOWER_ARGS = value_args_model([
|
|
1677
|
+
{'name': 'string', 'type': 'string'}
|
|
1678
|
+
])
|
|
1679
|
+
|
|
1680
|
+
|
|
1681
|
+
# $function: stringNew
|
|
1682
|
+
# $group: string
|
|
1683
|
+
# $doc: Create a new string from a value
|
|
1684
|
+
# $arg value: The value
|
|
1685
|
+
# $return: The new string
|
|
1686
|
+
def _string_new(args, unused_options):
|
|
1687
|
+
value, = value_args_validate(_STRING_NEW_ARGS, args)
|
|
1688
|
+
return value_string(value)
|
|
1689
|
+
|
|
1690
|
+
_STRING_NEW_ARGS = value_args_model([
|
|
1691
|
+
{'name': 'value'}
|
|
1692
|
+
])
|
|
1693
|
+
|
|
1694
|
+
|
|
1695
|
+
# $function: stringRepeat
|
|
1696
|
+
# $group: string
|
|
1697
|
+
# $doc: Repeat a string
|
|
1698
|
+
# $arg string: The string to repeat
|
|
1699
|
+
# $arg count: The number of times to repeat the string
|
|
1700
|
+
# $return: The repeated string
|
|
1701
|
+
def _string_repeat(args, unused_options):
|
|
1702
|
+
string, count = value_args_validate(_STRING_REPEAT_ARGS, args)
|
|
1703
|
+
return string * int(count)
|
|
1704
|
+
|
|
1705
|
+
_STRING_REPEAT_ARGS = value_args_model([
|
|
1706
|
+
{'name': 'string', 'type': 'string'},
|
|
1707
|
+
{'name': 'count', 'type': 'number', 'integer': True, 'gte': 0}
|
|
1708
|
+
])
|
|
1709
|
+
|
|
1710
|
+
|
|
1711
|
+
# $function: stringReplace
|
|
1712
|
+
# $group: string
|
|
1713
|
+
# $doc: Replace all instances of a string with another string
|
|
1714
|
+
# $arg string: The string to update
|
|
1715
|
+
# $arg substr: The string to replace
|
|
1716
|
+
# $arg newSubstr: The replacement string
|
|
1717
|
+
# $return: The updated string
|
|
1718
|
+
def _string_replace(args, unused_options):
|
|
1719
|
+
string, substr, new_substr = value_args_validate(_STRING_REPLACE_ARGS, args)
|
|
1720
|
+
return string.replace(substr, new_substr)
|
|
1721
|
+
|
|
1722
|
+
_STRING_REPLACE_ARGS = value_args_model([
|
|
1723
|
+
{'name': 'string', 'type': 'string'},
|
|
1724
|
+
{'name': 'substr', 'type': 'string'},
|
|
1725
|
+
{'name': 'newSubstr', 'type': 'string'}
|
|
1726
|
+
])
|
|
1727
|
+
|
|
1728
|
+
|
|
1729
|
+
# $function: stringSlice
|
|
1730
|
+
# $group: string
|
|
1731
|
+
# $doc: Copy a portion of a string
|
|
1732
|
+
# $arg string: The string
|
|
1733
|
+
# $arg start: The start index of the slice
|
|
1734
|
+
# $arg end: Optional (default is the end of the string). The end index of the slice.
|
|
1735
|
+
# $return: The new string slice
|
|
1736
|
+
def _string_slice(args, unused_options):
|
|
1737
|
+
string, start, end = value_args_validate(_STRING_SLICE_ARGS, args)
|
|
1738
|
+
end = end if end is not None else len(string)
|
|
1739
|
+
if start > len(string):
|
|
1740
|
+
raise ValueArgsError('start', start)
|
|
1741
|
+
if end > len(string):
|
|
1742
|
+
raise ValueArgsError('end', end)
|
|
1743
|
+
|
|
1744
|
+
return string[int(start):int(end)]
|
|
1745
|
+
|
|
1746
|
+
_STRING_SLICE_ARGS = value_args_model([
|
|
1747
|
+
{'name': 'string', 'type': 'string'},
|
|
1748
|
+
{'name': 'start', 'type': 'number', 'integer': True, 'gte': 0},
|
|
1749
|
+
{'name': 'end', 'type': 'number', 'nullable': True, 'integer': True, 'gte': 0}
|
|
1750
|
+
])
|
|
1751
|
+
|
|
1752
|
+
|
|
1753
|
+
# $function: stringSplit
|
|
1754
|
+
# $group: string
|
|
1755
|
+
# $doc: Split a string
|
|
1756
|
+
# $arg string: The string to split
|
|
1757
|
+
# $arg separator: The separator string
|
|
1758
|
+
# $return: The array of split-out strings
|
|
1759
|
+
def _string_split(args, unused_options):
|
|
1760
|
+
string, separator = value_args_validate(_STRING_SPLIT_ARGS, args)
|
|
1761
|
+
return string.split(separator)
|
|
1762
|
+
|
|
1763
|
+
_STRING_SPLIT_ARGS = value_args_model([
|
|
1764
|
+
{'name': 'string', 'type': 'string'},
|
|
1765
|
+
{'name': 'separator', 'type': 'string'}
|
|
1766
|
+
])
|
|
1767
|
+
|
|
1768
|
+
|
|
1769
|
+
# $function: stringStartsWith
|
|
1770
|
+
# $group: string
|
|
1771
|
+
# $doc: Determine if a string starts with a search string
|
|
1772
|
+
# $arg string: The string
|
|
1773
|
+
# $arg search: The search string
|
|
1774
|
+
# $return: true if the string starts with the search string, false otherwise
|
|
1775
|
+
def _string_starts_with(args, unused_options):
|
|
1776
|
+
string, search = value_args_validate(_STRING_STARTS_WITH_ARGS, args)
|
|
1777
|
+
return string.startswith(search)
|
|
1778
|
+
|
|
1779
|
+
_STRING_STARTS_WITH_ARGS = value_args_model([
|
|
1780
|
+
{'name': 'string', 'type': 'string'},
|
|
1781
|
+
{'name': 'search', 'type': 'string'}
|
|
1782
|
+
])
|
|
1783
|
+
|
|
1784
|
+
|
|
1785
|
+
# $function: stringTrim
|
|
1786
|
+
# $group: string
|
|
1787
|
+
# $doc: Trim the whitespace from the beginning and end of a string
|
|
1788
|
+
# $arg string: The string
|
|
1789
|
+
# $return: The trimmed string
|
|
1790
|
+
def _string_trim(args, unused_options):
|
|
1791
|
+
string, = value_args_validate(_STRING_TRIM_ARGS, args)
|
|
1792
|
+
return string.strip()
|
|
1793
|
+
|
|
1794
|
+
_STRING_TRIM_ARGS = value_args_model([
|
|
1795
|
+
{'name': 'string', 'type': 'string'}
|
|
1796
|
+
])
|
|
1797
|
+
|
|
1798
|
+
|
|
1799
|
+
# $function: stringUpper
|
|
1800
|
+
# $group: string
|
|
1801
|
+
# $doc: Convert a string to upper-case
|
|
1802
|
+
# $arg string: The string
|
|
1803
|
+
# $return: The upper-case string
|
|
1804
|
+
def _string_upper(args, unused_options):
|
|
1805
|
+
string, = value_args_validate(_STRING_UPPER_ARGS, args)
|
|
1806
|
+
return string.upper()
|
|
1807
|
+
|
|
1808
|
+
_STRING_UPPER_ARGS = value_args_model([
|
|
1809
|
+
{'name': 'string', 'type': 'string'}
|
|
1810
|
+
])
|
|
1811
|
+
|
|
1812
|
+
|
|
1813
|
+
#
|
|
1814
|
+
# System functions
|
|
1815
|
+
#
|
|
1816
|
+
|
|
1817
|
+
|
|
1818
|
+
# $function: systemBoolean
|
|
1819
|
+
# $group: system
|
|
1820
|
+
# $doc: Interpret a value as a boolean
|
|
1821
|
+
# $arg value: The value
|
|
1822
|
+
# $return: true or false
|
|
1823
|
+
def _system_boolean(args, unused_options):
|
|
1824
|
+
value, = value_args_validate(_SYSTEM_BOOLEAN_ARGS, args)
|
|
1825
|
+
return value_boolean(value)
|
|
1826
|
+
|
|
1827
|
+
_SYSTEM_BOOLEAN_ARGS = value_args_model([
|
|
1828
|
+
{'name': 'value'}
|
|
1829
|
+
])
|
|
1830
|
+
|
|
1831
|
+
|
|
1832
|
+
# $function: systemCompare
|
|
1833
|
+
# $group: system
|
|
1834
|
+
# $doc: Compare two values
|
|
1835
|
+
# $arg left: The left value
|
|
1836
|
+
# $arg right: The right value
|
|
1837
|
+
# $return: -1 if the left value is less than the right value, 0 if equal, and 1 if greater than
|
|
1838
|
+
def _system_compare(args, unused_options):
|
|
1839
|
+
left, right = value_args_validate(_SYSTEM_COMPARE_ARGS, args)
|
|
1840
|
+
return value_compare(left, right)
|
|
1841
|
+
|
|
1842
|
+
_SYSTEM_COMPARE_ARGS = value_args_model([
|
|
1843
|
+
{'name': 'left'},
|
|
1844
|
+
{'name': 'right'}
|
|
1845
|
+
])
|
|
1846
|
+
|
|
1847
|
+
|
|
1848
|
+
# $function: systemFetch
|
|
1849
|
+
# $group: system
|
|
1850
|
+
# $doc: Retrieve a URL resource
|
|
1851
|
+
# $arg url: The resource URL,
|
|
1852
|
+
# $arg url: [request model](https://craigahobbs.github.io/bare-script-py/library/model.html#var.vName='SystemFetchRequest'),
|
|
1853
|
+
# $arg url: or array of URL and
|
|
1854
|
+
# $arg url: [request model](https://craigahobbs.github.io/bare-script-py/library/model.html#var.vName='SystemFetchRequest')
|
|
1855
|
+
# $return: The response string or array of strings; null if an error occurred
|
|
1856
|
+
def _system_fetch(args, options):
|
|
1857
|
+
url, = value_args_validate(_SYSTEM_FETCH_ARGS, args)
|
|
1858
|
+
|
|
1859
|
+
# Options
|
|
1860
|
+
fetch_fn = options.get('fetchFn') if options is not None else None
|
|
1861
|
+
log_fn = options.get('logFn') if options is not None and options.get('debug') else None
|
|
1862
|
+
url_fn = options.get('urlFn') if options is not None else None
|
|
1863
|
+
|
|
1864
|
+
# Validate the URL argument
|
|
1865
|
+
requests = []
|
|
1866
|
+
is_response_array = False
|
|
1867
|
+
url_type = value_type(url)
|
|
1868
|
+
if url_type == 'string':
|
|
1869
|
+
requests.append({'url': url})
|
|
1870
|
+
elif url_type == 'object':
|
|
1871
|
+
requests.append(validate_type(SYSTEM_FETCH_TYPES, 'SystemFetchRequest', url))
|
|
1872
|
+
elif url_type == 'array':
|
|
1873
|
+
is_response_array = True
|
|
1874
|
+
for url_item in url:
|
|
1875
|
+
if value_type(url_item) == 'string':
|
|
1876
|
+
requests.append({'url': url_item})
|
|
1877
|
+
else:
|
|
1878
|
+
requests.append(validate_type(SYSTEM_FETCH_TYPES, 'SystemFetchRequest', url_item))
|
|
1879
|
+
else:
|
|
1880
|
+
raise ValueArgsError('url', url)
|
|
1881
|
+
|
|
1882
|
+
# Get each response
|
|
1883
|
+
responses = []
|
|
1884
|
+
for request in requests:
|
|
1885
|
+
request_fetch = dict(request)
|
|
1886
|
+
|
|
1887
|
+
# Update the URL
|
|
1888
|
+
if url_fn is not None:
|
|
1889
|
+
request_fetch['url'] = url_fn(request_fetch['url'])
|
|
1890
|
+
|
|
1891
|
+
# Fetch the URL
|
|
1892
|
+
response = None
|
|
1893
|
+
if fetch_fn is not None:
|
|
1894
|
+
try:
|
|
1895
|
+
response = fetch_fn(request_fetch)
|
|
1896
|
+
except:
|
|
1897
|
+
pass
|
|
1898
|
+
responses.append(response)
|
|
1899
|
+
|
|
1900
|
+
# Log failure
|
|
1901
|
+
if response is None and log_fn is not None:
|
|
1902
|
+
log_fn(f'BareScript: Function "systemFetch" failed for resource "{request_fetch["url"]}"')
|
|
1903
|
+
|
|
1904
|
+
return responses if is_response_array else responses[0]
|
|
1905
|
+
|
|
1906
|
+
_SYSTEM_FETCH_ARGS = value_args_model([
|
|
1907
|
+
{'name': 'url'}
|
|
1908
|
+
])
|
|
1909
|
+
|
|
1910
|
+
|
|
1911
|
+
# The aggregation model
|
|
1912
|
+
SYSTEM_FETCH_TYPES = parse_schema_markdown('''\
|
|
1913
|
+
group "SystemFetch"
|
|
1914
|
+
|
|
1915
|
+
|
|
1916
|
+
# A fetch request model
|
|
1917
|
+
struct SystemFetchRequest
|
|
1918
|
+
|
|
1919
|
+
# The resource URL
|
|
1920
|
+
string url
|
|
1921
|
+
|
|
1922
|
+
# The request body
|
|
1923
|
+
optional string body
|
|
1924
|
+
|
|
1925
|
+
# The request headers
|
|
1926
|
+
optional string{} headers
|
|
1927
|
+
''')
|
|
1928
|
+
|
|
1929
|
+
|
|
1930
|
+
# $function: systemGlobalGet
|
|
1931
|
+
# $group: system
|
|
1932
|
+
# $doc: Get a global variable value
|
|
1933
|
+
# $arg name: The global variable name
|
|
1934
|
+
# $arg defaultValue: The default value (optional)
|
|
1935
|
+
# $return: The global variable's value or null if it does not exist
|
|
1936
|
+
def _system_global_get(args, options):
|
|
1937
|
+
name, default_value = value_args_validate(_SYSTEM_GLOBAL_GET_ARGS, args)
|
|
1938
|
+
globals_ = options.get('globals') if options is not None else None
|
|
1939
|
+
return globals_.get(name, default_value) if globals_ is not None else default_value
|
|
1940
|
+
|
|
1941
|
+
_SYSTEM_GLOBAL_GET_ARGS = value_args_model([
|
|
1942
|
+
{'name': 'name', 'type': 'string'},
|
|
1943
|
+
{'name': 'defaultValue'}
|
|
1944
|
+
])
|
|
1945
|
+
|
|
1946
|
+
|
|
1947
|
+
# System includes object global variable name
|
|
1948
|
+
SYSTEM_GLOBAL_INCLUDES_NAME = '__bareScriptIncludes'
|
|
1949
|
+
|
|
1950
|
+
|
|
1951
|
+
# $function: systemGlobalIncludesGet
|
|
1952
|
+
# $group: system
|
|
1953
|
+
# $doc: Get the global system includes object
|
|
1954
|
+
# $return: The global system includes object
|
|
1955
|
+
def _system_global_includes_get(unused_args, options):
|
|
1956
|
+
globals_ = options.get('globals') if options is not None else None
|
|
1957
|
+
return globals_.get(SYSTEM_GLOBAL_INCLUDES_NAME) if globals_ is not None else None
|
|
1958
|
+
|
|
1959
|
+
|
|
1960
|
+
# $function: systemGlobalIncludesName
|
|
1961
|
+
# $group: system
|
|
1962
|
+
# $doc: Get the system includes object global variable name
|
|
1963
|
+
# $return: The system includes object global variable name
|
|
1964
|
+
def _system_global_includes_name(unused_args, unused_options):
|
|
1965
|
+
return SYSTEM_GLOBAL_INCLUDES_NAME
|
|
1966
|
+
|
|
1967
|
+
|
|
1968
|
+
# $function: systemGlobalSet
|
|
1969
|
+
# $group: system
|
|
1970
|
+
# $doc: Set a global variable value
|
|
1971
|
+
# $arg name: The global variable name
|
|
1972
|
+
# $arg value: The global variable's value
|
|
1973
|
+
# $return: The global variable's value
|
|
1974
|
+
def _system_global_set(args, options):
|
|
1975
|
+
name, value = value_args_validate(_SYSTEM_GLOBAL_SET_ARGS, args)
|
|
1976
|
+
globals_ = options.get('globals') if options is not None else None
|
|
1977
|
+
if globals_ is not None:
|
|
1978
|
+
globals_[name] = value
|
|
1979
|
+
return value
|
|
1980
|
+
|
|
1981
|
+
_SYSTEM_GLOBAL_SET_ARGS = value_args_model([
|
|
1982
|
+
{'name': 'name', 'type': 'string'},
|
|
1983
|
+
{'name': 'value'}
|
|
1984
|
+
])
|
|
1985
|
+
|
|
1986
|
+
|
|
1987
|
+
# $function: systemIs
|
|
1988
|
+
# $group: system
|
|
1989
|
+
# $doc: Test if one value is the same object as another
|
|
1990
|
+
# $arg value1: The first value
|
|
1991
|
+
# $arg value2: The second value
|
|
1992
|
+
# $return: true if values are the same object, false otherwise
|
|
1993
|
+
def _system_is(args, unused_options):
|
|
1994
|
+
value1, value2 = value_args_validate(_SYSTEM_IS_ARGS, args)
|
|
1995
|
+
return value_is(value1, value2)
|
|
1996
|
+
|
|
1997
|
+
_SYSTEM_IS_ARGS = value_args_model([
|
|
1998
|
+
{'name': 'value1'},
|
|
1999
|
+
{'name': 'value2'}
|
|
2000
|
+
])
|
|
2001
|
+
|
|
2002
|
+
|
|
2003
|
+
# $function: systemLog
|
|
2004
|
+
# $group: system
|
|
2005
|
+
# $doc: Log a message to the console
|
|
2006
|
+
# $arg message: The log message
|
|
2007
|
+
def _system_log(args, options):
|
|
2008
|
+
message, = value_args_validate(_SYSTEM_LOG_ARGS, args)
|
|
2009
|
+
log_fn = options.get('logFn') if options is not None else None
|
|
2010
|
+
if log_fn is not None:
|
|
2011
|
+
log_fn(value_string(message))
|
|
2012
|
+
|
|
2013
|
+
_SYSTEM_LOG_ARGS = value_args_model([
|
|
2014
|
+
{'name': 'message'}
|
|
2015
|
+
])
|
|
2016
|
+
|
|
2017
|
+
|
|
2018
|
+
# $function: systemLogDebug
|
|
2019
|
+
# $group: system
|
|
2020
|
+
# $doc: Log a message to the console, if in debug mode
|
|
2021
|
+
# $arg message: The log message
|
|
2022
|
+
def _system_log_debug(args, options):
|
|
2023
|
+
message, = value_args_validate(_SYSTEM_LOG_DEBUG_ARGS, args)
|
|
2024
|
+
log_fn = options.get('logFn') if options is not None else None
|
|
2025
|
+
if log_fn is not None and options.get('debug'):
|
|
2026
|
+
log_fn(value_string(message))
|
|
2027
|
+
|
|
2028
|
+
_SYSTEM_LOG_DEBUG_ARGS = value_args_model([
|
|
2029
|
+
{'name': 'message'}
|
|
2030
|
+
])
|
|
2031
|
+
|
|
2032
|
+
|
|
2033
|
+
# $function: systemPartial
|
|
2034
|
+
# $group: system
|
|
2035
|
+
# $doc: Return a new function which behaves like "func" called with "args".
|
|
2036
|
+
# $doc: If additional arguments are passed to the returned function, they are appended to "args".
|
|
2037
|
+
# $arg func: The function
|
|
2038
|
+
# $arg args...: The function arguments
|
|
2039
|
+
# $return: The new function called with "args"
|
|
2040
|
+
def _system_partial(args, unused_options):
|
|
2041
|
+
func, func_args = value_args_validate(_SYSTEM_PARTIAL_ARGS, args)
|
|
2042
|
+
if len(func_args) < 1:
|
|
2043
|
+
raise ValueArgsError('args', func_args)
|
|
2044
|
+
|
|
2045
|
+
return lambda args_extra, options: func([*func_args, *args_extra], options)
|
|
2046
|
+
|
|
2047
|
+
_SYSTEM_PARTIAL_ARGS = value_args_model([
|
|
2048
|
+
{'name': 'func', 'type': 'function'},
|
|
2049
|
+
{'name': 'args', 'lastArgArray': True}
|
|
2050
|
+
])
|
|
2051
|
+
|
|
2052
|
+
|
|
2053
|
+
# $function: systemType
|
|
2054
|
+
# $group: system
|
|
2055
|
+
# $doc: Get a value's type string
|
|
2056
|
+
# $arg value: The value
|
|
2057
|
+
# $return: The type string of the value.
|
|
2058
|
+
# $return: Valid values are: 'array', 'boolean', 'datetime', 'function', 'null', 'number', 'object', 'regex', 'string'.
|
|
2059
|
+
def _system_type(args, unused_options):
|
|
2060
|
+
value, = value_args_validate(_SYSTEM_TYPE_ARGS, args)
|
|
2061
|
+
return value_type(value)
|
|
2062
|
+
|
|
2063
|
+
_SYSTEM_TYPE_ARGS = value_args_model([
|
|
2064
|
+
{'name': 'value'}
|
|
2065
|
+
])
|
|
2066
|
+
|
|
2067
|
+
|
|
2068
|
+
#
|
|
2069
|
+
# URL functions
|
|
2070
|
+
#
|
|
2071
|
+
|
|
2072
|
+
|
|
2073
|
+
# $function: urlEncode
|
|
2074
|
+
# $group: url
|
|
2075
|
+
# $doc: Encode a URL
|
|
2076
|
+
# $arg url: The URL string
|
|
2077
|
+
# $return: The encoded URL string
|
|
2078
|
+
def _url_encode(args, unused_options):
|
|
2079
|
+
url, = value_args_validate(_URL_ENCODE_ARGS, args)
|
|
2080
|
+
return urllib.parse.quote(url, safe="':/&+!#=")
|
|
2081
|
+
|
|
2082
|
+
_URL_ENCODE_ARGS = value_args_model([
|
|
2083
|
+
{'name': 'url', 'type': 'string'}
|
|
2084
|
+
])
|
|
2085
|
+
|
|
2086
|
+
|
|
2087
|
+
# $function: urlEncodeComponent
|
|
2088
|
+
# $group: url
|
|
2089
|
+
# $doc: Encode a URL component
|
|
2090
|
+
# $arg url: The URL component string
|
|
2091
|
+
# $return: The encoded URL component string
|
|
2092
|
+
def _url_encode_component(args, unused_options):
|
|
2093
|
+
url, = value_args_validate(_URL_ENCODE_COMPONENT_ARGS, args)
|
|
2094
|
+
return urllib.parse.quote(url, safe="'")
|
|
2095
|
+
|
|
2096
|
+
_URL_ENCODE_COMPONENT_ARGS = value_args_model([
|
|
2097
|
+
{'name': 'url', 'type': 'string'}
|
|
2098
|
+
])
|
|
2099
|
+
|
|
2100
|
+
|
|
2101
|
+
# The built-in script functions
|
|
2102
|
+
SCRIPT_FUNCTIONS = {
|
|
2103
|
+
'arrayCopy': _array_copy,
|
|
2104
|
+
'arrayDelete': _array_delete,
|
|
2105
|
+
'arrayExtend': _array_extend,
|
|
2106
|
+
'arrayFlat': _array_flat,
|
|
2107
|
+
'arrayGet': _array_get,
|
|
2108
|
+
'arrayIndexOf': _array_index_of,
|
|
2109
|
+
'arrayJoin': _array_join,
|
|
2110
|
+
'arrayLastIndexOf': _array_last_index_of,
|
|
2111
|
+
'arrayLength': _array_length,
|
|
2112
|
+
'arrayNew': _array_new,
|
|
2113
|
+
'arrayNewSize': _array_new_size,
|
|
2114
|
+
'arrayPop': _array_pop,
|
|
2115
|
+
'arrayPush': _array_push,
|
|
2116
|
+
'arraySet': _array_set,
|
|
2117
|
+
'arrayShift': _array_shift,
|
|
2118
|
+
'arraySlice': _array_slice,
|
|
2119
|
+
'arraySort': _array_sort,
|
|
2120
|
+
'coverageGlobalGet': _coverage_global_get,
|
|
2121
|
+
'coverageGlobalName': _coverage_global_name,
|
|
2122
|
+
'coverageStart': _coverage_start,
|
|
2123
|
+
'coverageStop': _coverage_stop,
|
|
2124
|
+
'dataAggregate': _data_aggregate,
|
|
2125
|
+
'dataCalculatedField': _data_calculated_field,
|
|
2126
|
+
'dataFilter': _data_filter,
|
|
2127
|
+
'dataJoin': _data_join,
|
|
2128
|
+
'dataParseCSV': _data_parse_csv,
|
|
2129
|
+
'dataSort': _data_sort,
|
|
2130
|
+
'dataTop': _data_top,
|
|
2131
|
+
'dataValidate': _data_validate,
|
|
2132
|
+
'datetimeDay': _datetime_day,
|
|
2133
|
+
'datetimeHour': _datetime_hour,
|
|
2134
|
+
'datetimeISOFormat': _datetime_iso_format,
|
|
2135
|
+
'datetimeISOParse': _datetime_iso_parse,
|
|
2136
|
+
'datetimeMillisecond': _datetime_millisecond,
|
|
2137
|
+
'datetimeMinute': _datetime_minute,
|
|
2138
|
+
'datetimeMonth': _datetime_month,
|
|
2139
|
+
'datetimeNew': _datetime_new,
|
|
2140
|
+
'datetimeNow': _datetime_now,
|
|
2141
|
+
'datetimeSecond': _datetime_second,
|
|
2142
|
+
'datetimeToday': _datetime_today,
|
|
2143
|
+
'datetimeYear': _datetime_year,
|
|
2144
|
+
'jsonParse': _json_parse,
|
|
2145
|
+
'jsonStringify': _json_stringify,
|
|
2146
|
+
'mathAbs': _math_abs,
|
|
2147
|
+
'mathAcos': _math_acos,
|
|
2148
|
+
'mathAsin': _math_asin,
|
|
2149
|
+
'mathAtan': _math_atan,
|
|
2150
|
+
'mathAtan2': _math_atan2,
|
|
2151
|
+
'mathCeil': _math_ceil,
|
|
2152
|
+
'mathCos': _math_cos,
|
|
2153
|
+
'mathFloor': _math_floor,
|
|
2154
|
+
'mathLn': _math_ln,
|
|
2155
|
+
'mathLog': _math_log,
|
|
2156
|
+
'mathMax': _math_max,
|
|
2157
|
+
'mathMin': _math_min,
|
|
2158
|
+
'mathPi': _math_pi,
|
|
2159
|
+
'mathRandom': _math_random,
|
|
2160
|
+
'mathRound': _math_round,
|
|
2161
|
+
'mathSign': _math_sign,
|
|
2162
|
+
'mathSin': _math_sin,
|
|
2163
|
+
'mathSqrt': _math_sqrt,
|
|
2164
|
+
'mathTan': _math_tan,
|
|
2165
|
+
'numberParseInt': _number_parse_int,
|
|
2166
|
+
'numberParseFloat': _number_parse_float,
|
|
2167
|
+
'numberToFixed': _number_to_fixed,
|
|
2168
|
+
'objectAssign': _object_assign,
|
|
2169
|
+
'objectCopy': _object_copy,
|
|
2170
|
+
'objectDelete': _object_delete,
|
|
2171
|
+
'objectGet': _object_get,
|
|
2172
|
+
'objectHas': _object_has,
|
|
2173
|
+
'objectKeys': _object_keys,
|
|
2174
|
+
'objectNew': _object_new,
|
|
2175
|
+
'objectSet': _object_set,
|
|
2176
|
+
'regexEscape': _regex_escape,
|
|
2177
|
+
'regexMatch': _regex_match,
|
|
2178
|
+
'regexMatchAll': _regex_match_all,
|
|
2179
|
+
'regexNew': _regex_new,
|
|
2180
|
+
'regexReplace': _regex_replace,
|
|
2181
|
+
'regexSplit': _regex_split,
|
|
2182
|
+
'schemaParse': _schema_parse,
|
|
2183
|
+
'schemaParseEx': _schema_parse_ex,
|
|
2184
|
+
'schemaTypeModel': _schema_type_model,
|
|
2185
|
+
'schemaValidate': _schema_validate,
|
|
2186
|
+
'schemaValidateTypeModel': _schema_validate_type_model,
|
|
2187
|
+
'stringCharCodeAt': _string_char_code_at,
|
|
2188
|
+
'stringEndsWith': _string_ends_with,
|
|
2189
|
+
'stringFromCharCode': _string_from_char_code,
|
|
2190
|
+
'stringIndexOf': _string_index_of,
|
|
2191
|
+
'stringLastIndexOf': _string_last_index_of,
|
|
2192
|
+
'stringLength': _string_length,
|
|
2193
|
+
'stringLower': _string_lower,
|
|
2194
|
+
'stringNew': _string_new,
|
|
2195
|
+
'stringRepeat': _string_repeat,
|
|
2196
|
+
'stringReplace': _string_replace,
|
|
2197
|
+
'stringSlice': _string_slice,
|
|
2198
|
+
'stringSplit': _string_split,
|
|
2199
|
+
'stringStartsWith': _string_starts_with,
|
|
2200
|
+
'stringTrim': _string_trim,
|
|
2201
|
+
'stringUpper': _string_upper,
|
|
2202
|
+
'systemBoolean': _system_boolean,
|
|
2203
|
+
'systemCompare': _system_compare,
|
|
2204
|
+
'systemFetch': _system_fetch,
|
|
2205
|
+
'systemGlobalGet': _system_global_get,
|
|
2206
|
+
'systemGlobalIncludesGet': _system_global_includes_get,
|
|
2207
|
+
'systemGlobalIncludesName': _system_global_includes_name,
|
|
2208
|
+
'systemGlobalSet': _system_global_set,
|
|
2209
|
+
'systemIs': _system_is,
|
|
2210
|
+
'systemLog': _system_log,
|
|
2211
|
+
'systemLogDebug': _system_log_debug,
|
|
2212
|
+
'systemPartial': _system_partial,
|
|
2213
|
+
'systemType': _system_type,
|
|
2214
|
+
'urlEncode': _url_encode,
|
|
2215
|
+
'urlEncodeComponent': _url_encode_component
|
|
2216
|
+
}
|
|
2217
|
+
|
|
2218
|
+
|
|
2219
|
+
# The built-in expression functions
|
|
2220
|
+
EXPRESSION_FUNCTION_MAP = {
|
|
2221
|
+
'abs': 'mathAbs',
|
|
2222
|
+
'acos': 'mathAcos',
|
|
2223
|
+
'arrayNew': 'arrayNew',
|
|
2224
|
+
'asin': 'mathAsin',
|
|
2225
|
+
'atan': 'mathAtan',
|
|
2226
|
+
'atan2': 'mathAtan2',
|
|
2227
|
+
'ceil': 'mathCeil',
|
|
2228
|
+
'charCodeAt': 'stringCharCodeAt',
|
|
2229
|
+
'cos': 'mathCos',
|
|
2230
|
+
'date': 'datetimeNew',
|
|
2231
|
+
'day': 'datetimeDay',
|
|
2232
|
+
'endsWith': 'stringEndsWith',
|
|
2233
|
+
'indexOf': 'stringIndexOf',
|
|
2234
|
+
'fixed': 'numberToFixed',
|
|
2235
|
+
'floor': 'mathFloor',
|
|
2236
|
+
'fromCharCode': 'stringFromCharCode',
|
|
2237
|
+
'hour': 'datetimeHour',
|
|
2238
|
+
'lastIndexOf': 'stringLastIndexOf',
|
|
2239
|
+
'len': 'stringLength',
|
|
2240
|
+
'lower': 'stringLower',
|
|
2241
|
+
'ln': 'mathLn',
|
|
2242
|
+
'log': 'mathLog',
|
|
2243
|
+
'max': 'mathMax',
|
|
2244
|
+
'min': 'mathMin',
|
|
2245
|
+
'millisecond': 'datetimeMillisecond',
|
|
2246
|
+
'minute': 'datetimeMinute',
|
|
2247
|
+
'month': 'datetimeMonth',
|
|
2248
|
+
'now': 'datetimeNow',
|
|
2249
|
+
'objectNew': 'objectNew',
|
|
2250
|
+
'parseInt': 'numberParseInt',
|
|
2251
|
+
'parseFloat': 'numberParseFloat',
|
|
2252
|
+
'pi': 'mathPi',
|
|
2253
|
+
'rand': 'mathRandom',
|
|
2254
|
+
'replace': 'stringReplace',
|
|
2255
|
+
'rept': 'stringRepeat',
|
|
2256
|
+
'round': 'mathRound',
|
|
2257
|
+
'second': 'datetimeSecond',
|
|
2258
|
+
'sign': 'mathSign',
|
|
2259
|
+
'sin': 'mathSin',
|
|
2260
|
+
'slice': 'stringSlice',
|
|
2261
|
+
'sqrt': 'mathSqrt',
|
|
2262
|
+
'startsWith': 'stringStartsWith',
|
|
2263
|
+
'text': 'stringNew',
|
|
2264
|
+
'tan': 'mathTan',
|
|
2265
|
+
'today': 'datetimeToday',
|
|
2266
|
+
'trim': 'stringTrim',
|
|
2267
|
+
'upper': 'stringUpper',
|
|
2268
|
+
'year': 'datetimeYear'
|
|
2269
|
+
}
|
|
2270
|
+
EXPRESSION_FUNCTIONS = dict(
|
|
2271
|
+
(expr_fn_name, SCRIPT_FUNCTIONS[script_fn_name])
|
|
2272
|
+
for expr_fn_name, script_fn_name in EXPRESSION_FUNCTION_MAP.items()
|
|
2273
|
+
)
|