rapydscript-ns 0.9.3 → 0.9.4
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.
- package/.agignore +1 -1
- package/.github/workflows/ci.yml +38 -38
- package/=template.pyj +5 -5
- package/CHANGELOG.md +9 -0
- package/HACKING.md +103 -103
- package/LICENSE +24 -24
- package/PYTHON_GAPS.md +48 -116
- package/README.md +35 -15
- package/TODO.md +1 -26
- package/add-toc-to-readme +2 -2
- package/bin/export +75 -75
- package/bin/rapydscript +0 -0
- package/bin/web-repl-export +102 -102
- package/build +2 -2
- package/language-service/index.js +9 -7
- package/package.json +1 -1
- package/publish.py +37 -37
- package/session.vim +4 -4
- package/setup.cfg +2 -2
- package/src/ast.pyj +6 -0
- package/src/baselib-containers.pyj +23 -1
- package/src/baselib-str.pyj +13 -2
- package/src/compiler.pyj +36 -36
- package/src/errors.pyj +30 -30
- package/src/lib/aes.pyj +646 -646
- package/src/lib/collections.pyj +227 -3
- package/src/lib/copy.pyj +120 -120
- package/src/lib/elementmaker.pyj +83 -83
- package/src/lib/encodings.pyj +126 -126
- package/src/lib/gettext.pyj +569 -569
- package/src/lib/itertools.pyj +580 -580
- package/src/lib/math.pyj +193 -193
- package/src/lib/operator.pyj +11 -11
- package/src/lib/pprint.pyj +455 -0
- package/src/lib/random.pyj +118 -118
- package/src/lib/react.pyj +74 -74
- package/src/lib/statistics.pyj +0 -0
- package/src/lib/traceback.pyj +63 -63
- package/src/lib/uuid.pyj +77 -77
- package/src/monaco-language-service/diagnostics.js +2 -2
- package/src/monaco-language-service/dts.js +550 -550
- package/src/output/codegen.pyj +4 -1
- package/src/output/comments.pyj +45 -45
- package/src/output/exceptions.pyj +201 -201
- package/src/output/jsx.pyj +164 -164
- package/src/output/treeshake.pyj +182 -182
- package/src/output/utils.pyj +72 -72
- package/src/parse.pyj +28 -7
- package/src/string_interpolation.pyj +72 -72
- package/src/tokenizer.pyj +18 -2
- package/src/unicode_aliases.pyj +576 -576
- package/src/utils.pyj +192 -192
- package/test/_import_one.pyj +37 -37
- package/test/_import_two/__init__.pyj +11 -11
- package/test/_import_two/level2/deep.pyj +4 -4
- package/test/_import_two/other.pyj +6 -6
- package/test/_import_two/sub.pyj +13 -13
- package/test/aes_vectors.pyj +421 -421
- package/test/annotations.pyj +80 -80
- package/test/baselib.pyj +23 -0
- package/test/chainmap.pyj +185 -0
- package/test/decorators.pyj +77 -77
- package/test/docstrings.pyj +39 -39
- package/test/elementmaker_test.pyj +45 -45
- package/test/functions.pyj +151 -151
- package/test/generators.pyj +41 -41
- package/test/generic.pyj +370 -370
- package/test/internationalization.pyj +73 -73
- package/test/lint.pyj +164 -164
- package/test/loops.pyj +85 -85
- package/test/numpy.pyj +734 -734
- package/test/pprint.pyj +232 -0
- package/test/repl.pyj +121 -121
- package/test/scoped_flags.pyj +76 -76
- package/test/statistics.pyj +224 -0
- package/test/unit/index.js +80 -0
- package/test/unit/language-service-completions.js +2 -0
- package/test/unit/language-service-dts.js +543 -543
- package/test/unit/language-service-hover.js +455 -455
- package/test/unit/language-service.js +63 -2
- package/test/unit/web-repl.js +323 -0
- package/tools/compiler.d.ts +367 -367
- package/tools/completer.js +131 -131
- package/tools/export.js +4 -2
- package/tools/gettext.js +185 -185
- package/tools/ini.js +65 -65
- package/tools/msgfmt.js +187 -187
- package/tools/repl.js +223 -223
- package/tools/test.js +118 -118
- package/tools/utils.js +128 -128
- package/tools/web_repl.js +95 -95
- package/try +41 -41
- package/web-repl/env.js +196 -196
- package/web-repl/index.html +163 -163
- package/web-repl/prism.css +139 -139
- package/web-repl/prism.js +113 -113
- package/web-repl/rapydscript.js +228 -226
- package/web-repl/sha1.js +25 -25
|
@@ -0,0 +1,455 @@
|
|
|
1
|
+
###########################################################
|
|
2
|
+
# RapydScript Standard Library
|
|
3
|
+
# License: Apache License 2.0
|
|
4
|
+
# This library is covered under Apache license, so that
|
|
5
|
+
# you can distribute it with your RapydScript applications.
|
|
6
|
+
###########################################################
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
# Implementation of Python's 'pprint' module.
|
|
10
|
+
#
|
|
11
|
+
# Pretty-prints arbitrary RapydScript / Python data structures.
|
|
12
|
+
#
|
|
13
|
+
# A value's repr() is used when it fits within `width`; otherwise containers
|
|
14
|
+
# are broken across multiple lines with Python-style indentation.
|
|
15
|
+
#
|
|
16
|
+
# Public API:
|
|
17
|
+
# pformat(object, ...) -> str
|
|
18
|
+
# pprint(object, ...)
|
|
19
|
+
# pp(object, ...) same as pprint but defaults sort_dicts=False
|
|
20
|
+
# saferepr(object) repr() with recursive references marked
|
|
21
|
+
# isreadable(object) whether pformat output can be parsed back
|
|
22
|
+
# isrecursive(object) whether the object has recursive references
|
|
23
|
+
# class PrettyPrinter
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
# ── private helpers ─────────────────────────────────────────────────────────
|
|
27
|
+
|
|
28
|
+
v"""
|
|
29
|
+
function _pp_is_plain_dict_like(obj) {
|
|
30
|
+
if (obj === null || obj === undefined) return false;
|
|
31
|
+
if (typeof obj !== 'object') return false;
|
|
32
|
+
if (Array.isArray(obj)) return false;
|
|
33
|
+
if (obj.jsmap && typeof obj.jsmap.forEach === 'function') return false;
|
|
34
|
+
if (obj.jsset && typeof obj.jsset.values === 'function') return false;
|
|
35
|
+
var proto = Object.getPrototypeOf(obj);
|
|
36
|
+
return proto === null || proto === Object.prototype;
|
|
37
|
+
}
|
|
38
|
+
var _pp_id_counter = 0;
|
|
39
|
+
function _pp_id(obj) {
|
|
40
|
+
if (obj === null || obj === undefined) return 0;
|
|
41
|
+
if (typeof obj !== 'object') return 0;
|
|
42
|
+
if (!obj.__pp_id__) {
|
|
43
|
+
Object.defineProperty(obj, '__pp_id__',
|
|
44
|
+
{ value: ++_pp_id_counter, configurable: true, writable: true });
|
|
45
|
+
}
|
|
46
|
+
return obj.__pp_id__;
|
|
47
|
+
}
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def _try_repr(x):
|
|
52
|
+
try:
|
|
53
|
+
return repr(x)
|
|
54
|
+
except:
|
|
55
|
+
return str(x)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def _cmp_pair(a, b):
|
|
59
|
+
try:
|
|
60
|
+
if a[0] < b[0]:
|
|
61
|
+
return -1
|
|
62
|
+
if a[0] > b[0]:
|
|
63
|
+
return 1
|
|
64
|
+
return 0
|
|
65
|
+
except:
|
|
66
|
+
return 0
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def _cmp_value(a, b):
|
|
70
|
+
try:
|
|
71
|
+
if a < b:
|
|
72
|
+
return -1
|
|
73
|
+
if a > b:
|
|
74
|
+
return 1
|
|
75
|
+
return 0
|
|
76
|
+
except:
|
|
77
|
+
return 0
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def _is_dict(obj):
|
|
81
|
+
if isinstance(obj, dict):
|
|
82
|
+
return True
|
|
83
|
+
return v'_pp_is_plain_dict_like(obj)'
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def _get_dict_pairs(obj, sort_dicts):
|
|
87
|
+
pairs = v'[]'
|
|
88
|
+
if isinstance(obj, dict):
|
|
89
|
+
iterator = obj.items()
|
|
90
|
+
r = iterator.next()
|
|
91
|
+
while not r.done:
|
|
92
|
+
pairs.push(v'[r.value[0], r.value[1]]')
|
|
93
|
+
r = iterator.next()
|
|
94
|
+
else:
|
|
95
|
+
v"""
|
|
96
|
+
var _keys = Object.keys(obj);
|
|
97
|
+
for (var _i = 0; _i < _keys.length; _i++) {
|
|
98
|
+
pairs.push([_keys[_i], obj[_keys[_i]]]);
|
|
99
|
+
}
|
|
100
|
+
"""
|
|
101
|
+
if sort_dicts:
|
|
102
|
+
pairs.sort(_cmp_pair)
|
|
103
|
+
return pairs
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def _get_set_items(obj):
|
|
107
|
+
items = v'[]'
|
|
108
|
+
iterator = obj.jsset.values()
|
|
109
|
+
r = iterator.next()
|
|
110
|
+
while not r.done:
|
|
111
|
+
items.push(r.value)
|
|
112
|
+
r = iterator.next()
|
|
113
|
+
items.sort(_cmp_value)
|
|
114
|
+
return items
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def _recursion_marker(obj):
|
|
118
|
+
name = 'object'
|
|
119
|
+
try:
|
|
120
|
+
if obj.constructor and obj.constructor.name:
|
|
121
|
+
name = obj.constructor.name
|
|
122
|
+
elif isinstance(obj, dict):
|
|
123
|
+
name = 'dict'
|
|
124
|
+
elif isinstance(obj, set):
|
|
125
|
+
name = 'set'
|
|
126
|
+
elif Array.isArray(obj):
|
|
127
|
+
name = 'list'
|
|
128
|
+
except:
|
|
129
|
+
pass
|
|
130
|
+
return '<Recursion on ' + name + ' with id=' + str(v'_pp_id(obj)') + '>'
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def _safe_repr(obj, context, maxlevels, level, sort_dicts):
|
|
134
|
+
"""Return [repr_string, readable, recursive].
|
|
135
|
+
|
|
136
|
+
readable -- True if the output is parseable back by eval
|
|
137
|
+
recursive -- True if obj (or any sub-object) recursively contains itself
|
|
138
|
+
"""
|
|
139
|
+
if obj is None:
|
|
140
|
+
return v'["None", true, false]'
|
|
141
|
+
if obj is True:
|
|
142
|
+
return v'["True", true, false]'
|
|
143
|
+
if obj is False:
|
|
144
|
+
return v'["False", true, false]'
|
|
145
|
+
t = jstype(obj)
|
|
146
|
+
if t is 'number' or t is 'string' or t is 'bigint':
|
|
147
|
+
return v'[_try_repr(obj), true, false]'
|
|
148
|
+
|
|
149
|
+
obj_id = v'_pp_id(obj)'
|
|
150
|
+
|
|
151
|
+
if Array.isArray(obj):
|
|
152
|
+
if obj.length is 0:
|
|
153
|
+
return v'["[]", true, false]'
|
|
154
|
+
if maxlevels is not None and level >= maxlevels:
|
|
155
|
+
return v'["[...]", false, false]'
|
|
156
|
+
if context.has(obj):
|
|
157
|
+
return v'[_recursion_marker(obj), false, true]'
|
|
158
|
+
context.set(obj, 1)
|
|
159
|
+
components = v'[]'
|
|
160
|
+
readable = True
|
|
161
|
+
recursive = False
|
|
162
|
+
for v'var i = 0; i < obj.length; i++':
|
|
163
|
+
r = _safe_repr(obj[i], context, maxlevels, level + 1, sort_dicts)
|
|
164
|
+
components.push(r[0])
|
|
165
|
+
if not r[1]:
|
|
166
|
+
readable = False
|
|
167
|
+
if r[2]:
|
|
168
|
+
recursive = True
|
|
169
|
+
context.delete(obj)
|
|
170
|
+
return v'["[" + components.join(", ") + "]", readable, recursive]'
|
|
171
|
+
|
|
172
|
+
if isinstance(obj, set):
|
|
173
|
+
if obj.size is 0:
|
|
174
|
+
return v'["set()", false, false]'
|
|
175
|
+
if maxlevels is not None and level >= maxlevels:
|
|
176
|
+
return v'["{...}", false, false]'
|
|
177
|
+
if context.has(obj):
|
|
178
|
+
return v'[_recursion_marker(obj), false, true]'
|
|
179
|
+
context.set(obj, 1)
|
|
180
|
+
items = _get_set_items(obj)
|
|
181
|
+
components = v'[]'
|
|
182
|
+
readable = True
|
|
183
|
+
recursive = False
|
|
184
|
+
for v'var j = 0; j < items.length; j++':
|
|
185
|
+
r = _safe_repr(items[j], context, maxlevels, level + 1, sort_dicts)
|
|
186
|
+
components.push(r[0])
|
|
187
|
+
if not r[1]:
|
|
188
|
+
readable = False
|
|
189
|
+
if r[2]:
|
|
190
|
+
recursive = True
|
|
191
|
+
context.delete(obj)
|
|
192
|
+
return v'["{" + components.join(", ") + "}", readable, recursive]'
|
|
193
|
+
|
|
194
|
+
if isinstance(obj, frozenset):
|
|
195
|
+
if obj.size is 0:
|
|
196
|
+
return v'["frozenset()", true, false]'
|
|
197
|
+
if maxlevels is not None and level >= maxlevels:
|
|
198
|
+
return v'["frozenset({...})", false, false]'
|
|
199
|
+
items = _get_set_items(obj)
|
|
200
|
+
components = v'[]'
|
|
201
|
+
readable = True
|
|
202
|
+
recursive = False
|
|
203
|
+
for v'var k = 0; k < items.length; k++':
|
|
204
|
+
r = _safe_repr(items[k], context, maxlevels, level + 1, sort_dicts)
|
|
205
|
+
components.push(r[0])
|
|
206
|
+
if not r[1]:
|
|
207
|
+
readable = False
|
|
208
|
+
if r[2]:
|
|
209
|
+
recursive = True
|
|
210
|
+
return v'["frozenset({" + components.join(", ") + "})", readable, recursive]'
|
|
211
|
+
|
|
212
|
+
if _is_dict(obj):
|
|
213
|
+
pairs = _get_dict_pairs(obj, sort_dicts)
|
|
214
|
+
if pairs.length is 0:
|
|
215
|
+
return v'["{}", true, false]'
|
|
216
|
+
if maxlevels is not None and level >= maxlevels:
|
|
217
|
+
return v'["{...}", false, false]'
|
|
218
|
+
if context.has(obj):
|
|
219
|
+
return v'[_recursion_marker(obj), false, true]'
|
|
220
|
+
context.set(obj, 1)
|
|
221
|
+
components = v'[]'
|
|
222
|
+
readable = True
|
|
223
|
+
recursive = False
|
|
224
|
+
for v'var m = 0; m < pairs.length; m++':
|
|
225
|
+
kr = _safe_repr(pairs[m][0], context, maxlevels, level + 1, sort_dicts)
|
|
226
|
+
vr = _safe_repr(pairs[m][1], context, maxlevels, level + 1, sort_dicts)
|
|
227
|
+
components.push(kr[0] + ': ' + vr[0])
|
|
228
|
+
if not kr[1] or not vr[1]:
|
|
229
|
+
readable = False
|
|
230
|
+
if kr[2] or vr[2]:
|
|
231
|
+
recursive = True
|
|
232
|
+
context.delete(obj)
|
|
233
|
+
return v'["{" + components.join(", ") + "}", readable, recursive]'
|
|
234
|
+
|
|
235
|
+
# Class instance, function, etc. — fall back to repr().
|
|
236
|
+
rep = _try_repr(obj)
|
|
237
|
+
return v'[rep, false, false]'
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
# ── stream buffer used when no stream is given ──────────────────────────────
|
|
241
|
+
|
|
242
|
+
class _StreamBuffer:
|
|
243
|
+
def __init__(self):
|
|
244
|
+
self.parts = v'[]'
|
|
245
|
+
|
|
246
|
+
def write(self, s):
|
|
247
|
+
self.parts.push(s)
|
|
248
|
+
|
|
249
|
+
def getvalue(self):
|
|
250
|
+
return self.parts.join('')
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
# ── PrettyPrinter ───────────────────────────────────────────────────────────
|
|
254
|
+
|
|
255
|
+
class PrettyPrinter:
|
|
256
|
+
"""Handle pretty-printing operations onto a stream."""
|
|
257
|
+
|
|
258
|
+
def __init__(self, indent=1, width=80, depth=None, stream=None,
|
|
259
|
+
compact=False, sort_dicts=True, underscore_numbers=False):
|
|
260
|
+
if jstype(indent) is not 'number' or indent < 0:
|
|
261
|
+
raise ValueError('indent must be a non-negative integer')
|
|
262
|
+
if jstype(width) is not 'number' or width < 0:
|
|
263
|
+
raise ValueError('width must be a non-negative integer')
|
|
264
|
+
if depth is not None:
|
|
265
|
+
if jstype(depth) is not 'number' or depth <= 0:
|
|
266
|
+
raise ValueError('depth must be > 0')
|
|
267
|
+
self._depth = depth
|
|
268
|
+
self._indent_per_level = indent
|
|
269
|
+
self._width = width
|
|
270
|
+
self._compact = bool(compact)
|
|
271
|
+
self._sort_dicts = bool(sort_dicts)
|
|
272
|
+
self._underscore_numbers = bool(underscore_numbers)
|
|
273
|
+
self._stream = stream
|
|
274
|
+
|
|
275
|
+
def pprint(self, object):
|
|
276
|
+
if self._stream is not None:
|
|
277
|
+
self._format(object, self._stream, 0, 0, v'new Map()', 0)
|
|
278
|
+
self._stream.write('\n')
|
|
279
|
+
else:
|
|
280
|
+
print(self.pformat(object))
|
|
281
|
+
|
|
282
|
+
def pformat(self, object):
|
|
283
|
+
buf = _StreamBuffer()
|
|
284
|
+
self._format(object, buf, 0, 0, v'new Map()', 0)
|
|
285
|
+
return buf.getvalue()
|
|
286
|
+
|
|
287
|
+
def isreadable(self, object):
|
|
288
|
+
r = _safe_repr(object, v'new Map()', self._depth, 0, self._sort_dicts)
|
|
289
|
+
return r[1] and not r[2]
|
|
290
|
+
|
|
291
|
+
def isrecursive(self, object):
|
|
292
|
+
r = _safe_repr(object, v'new Map()', self._depth, 0, self._sort_dicts)
|
|
293
|
+
return r[2]
|
|
294
|
+
|
|
295
|
+
def _format(self, obj, stream, indent, allowance, context, level):
|
|
296
|
+
if obj is not None and jstype(obj) is 'object' and context.has(obj):
|
|
297
|
+
stream.write(_recursion_marker(obj))
|
|
298
|
+
return
|
|
299
|
+
|
|
300
|
+
rep = self._repr(obj, context, level)
|
|
301
|
+
max_width = self._width - indent - allowance
|
|
302
|
+
|
|
303
|
+
if rep.length <= max_width:
|
|
304
|
+
stream.write(rep)
|
|
305
|
+
return
|
|
306
|
+
|
|
307
|
+
# too wide -- try to expand the container across multiple lines
|
|
308
|
+
if Array.isArray(obj) and obj.length > 0:
|
|
309
|
+
if self._depth is not None and level >= self._depth:
|
|
310
|
+
stream.write(rep)
|
|
311
|
+
return
|
|
312
|
+
context.set(obj, 1)
|
|
313
|
+
stream.write('[')
|
|
314
|
+
self._format_items(obj, stream, indent, allowance + 1, context, level + 1)
|
|
315
|
+
stream.write(']')
|
|
316
|
+
context.delete(obj)
|
|
317
|
+
return
|
|
318
|
+
|
|
319
|
+
if isinstance(obj, set) and obj.size > 0:
|
|
320
|
+
if self._depth is not None and level >= self._depth:
|
|
321
|
+
stream.write(rep)
|
|
322
|
+
return
|
|
323
|
+
context.set(obj, 1)
|
|
324
|
+
items = _get_set_items(obj)
|
|
325
|
+
stream.write('{')
|
|
326
|
+
self._format_items(items, stream, indent, allowance + 1, context, level + 1)
|
|
327
|
+
stream.write('}')
|
|
328
|
+
context.delete(obj)
|
|
329
|
+
return
|
|
330
|
+
|
|
331
|
+
if isinstance(obj, frozenset) and obj.size > 0:
|
|
332
|
+
if self._depth is not None and level >= self._depth:
|
|
333
|
+
stream.write(rep)
|
|
334
|
+
return
|
|
335
|
+
items = _get_set_items(obj)
|
|
336
|
+
stream.write('frozenset({')
|
|
337
|
+
self._format_items(items, stream, indent + 10, allowance + 2, context, level + 1)
|
|
338
|
+
stream.write('})')
|
|
339
|
+
return
|
|
340
|
+
|
|
341
|
+
if _is_dict(obj):
|
|
342
|
+
pairs = _get_dict_pairs(obj, self._sort_dicts)
|
|
343
|
+
if pairs.length > 0:
|
|
344
|
+
if self._depth is not None and level >= self._depth:
|
|
345
|
+
stream.write(rep)
|
|
346
|
+
return
|
|
347
|
+
context.set(obj, 1)
|
|
348
|
+
stream.write('{')
|
|
349
|
+
if self._indent_per_level > 1:
|
|
350
|
+
stream.write(' '.repeat(self._indent_per_level - 1))
|
|
351
|
+
self._format_dict_items(pairs, stream, indent, allowance + 1, context, level + 1)
|
|
352
|
+
stream.write('}')
|
|
353
|
+
context.delete(obj)
|
|
354
|
+
return
|
|
355
|
+
|
|
356
|
+
stream.write(rep)
|
|
357
|
+
|
|
358
|
+
def _format_items(self, items, stream, indent, allowance, context, level):
|
|
359
|
+
indent = indent + self._indent_per_level
|
|
360
|
+
if self._indent_per_level > 1:
|
|
361
|
+
stream.write(' '.repeat(self._indent_per_level - 1))
|
|
362
|
+
delimnl = ',\n' + ' '.repeat(indent)
|
|
363
|
+
delim = ''
|
|
364
|
+
width = self._width - indent + 1
|
|
365
|
+
max_width = width
|
|
366
|
+
last_index = items.length - 1
|
|
367
|
+
for v'var i = 0; i < items.length; i++':
|
|
368
|
+
last = i is last_index
|
|
369
|
+
ent = items[i]
|
|
370
|
+
if self._compact:
|
|
371
|
+
rep = self._repr(ent, context, level)
|
|
372
|
+
w = rep.length + 2
|
|
373
|
+
if width < w:
|
|
374
|
+
width = max_width
|
|
375
|
+
if delim:
|
|
376
|
+
delim = delimnl
|
|
377
|
+
if width >= w:
|
|
378
|
+
width -= w
|
|
379
|
+
stream.write(delim)
|
|
380
|
+
delim = ', '
|
|
381
|
+
stream.write(rep)
|
|
382
|
+
continue
|
|
383
|
+
stream.write(delim)
|
|
384
|
+
delim = delimnl
|
|
385
|
+
self._format(ent, stream, indent,
|
|
386
|
+
allowance if last else 1,
|
|
387
|
+
context, level)
|
|
388
|
+
|
|
389
|
+
def _format_dict_items(self, items, stream, indent, allowance, context, level):
|
|
390
|
+
indent = indent + self._indent_per_level
|
|
391
|
+
delimnl = ',\n' + ' '.repeat(indent)
|
|
392
|
+
last_index = items.length - 1
|
|
393
|
+
for v'var i = 0; i < items.length; i++':
|
|
394
|
+
last = i is last_index
|
|
395
|
+
key = items[i][0]
|
|
396
|
+
ent = items[i][1]
|
|
397
|
+
rep = self._repr(key, context, level)
|
|
398
|
+
stream.write(rep)
|
|
399
|
+
stream.write(': ')
|
|
400
|
+
self._format(ent, stream, indent + rep.length + 2,
|
|
401
|
+
allowance if last else 1, context, level)
|
|
402
|
+
if not last:
|
|
403
|
+
stream.write(delimnl)
|
|
404
|
+
|
|
405
|
+
def _repr(self, obj, context, level):
|
|
406
|
+
r = _safe_repr(obj, context, self._depth, level, self._sort_dicts)
|
|
407
|
+
return r[0]
|
|
408
|
+
|
|
409
|
+
def format(self, object, context, maxlevels, level):
|
|
410
|
+
"""Hook for subclasses; returns (string, readable, recursive)."""
|
|
411
|
+
return _safe_repr(object, context, maxlevels, level, self._sort_dicts)
|
|
412
|
+
|
|
413
|
+
|
|
414
|
+
# ── module-level convenience functions ──────────────────────────────────────
|
|
415
|
+
|
|
416
|
+
def pformat(object, indent=1, width=80, depth=None, compact=False,
|
|
417
|
+
sort_dicts=True, underscore_numbers=False):
|
|
418
|
+
"""Pretty-print a value as a string."""
|
|
419
|
+
return PrettyPrinter(indent=indent, width=width, depth=depth,
|
|
420
|
+
compact=compact, sort_dicts=sort_dicts,
|
|
421
|
+
underscore_numbers=underscore_numbers).pformat(object)
|
|
422
|
+
|
|
423
|
+
|
|
424
|
+
def pprint(object, stream=None, indent=1, width=80, depth=None,
|
|
425
|
+
compact=False, sort_dicts=True, underscore_numbers=False):
|
|
426
|
+
"""Pretty-print a value to a stream, or to stdout if stream is None."""
|
|
427
|
+
PrettyPrinter(indent=indent, width=width, depth=depth, stream=stream,
|
|
428
|
+
compact=compact, sort_dicts=sort_dicts,
|
|
429
|
+
underscore_numbers=underscore_numbers).pprint(object)
|
|
430
|
+
|
|
431
|
+
|
|
432
|
+
def pp(object, stream=None, indent=1, width=80, depth=None,
|
|
433
|
+
compact=False, sort_dicts=False, underscore_numbers=False):
|
|
434
|
+
"""Pretty-print with sort_dicts=False by default."""
|
|
435
|
+
pprint(object, stream=stream, indent=indent, width=width, depth=depth,
|
|
436
|
+
compact=compact, sort_dicts=sort_dicts,
|
|
437
|
+
underscore_numbers=underscore_numbers)
|
|
438
|
+
|
|
439
|
+
|
|
440
|
+
def saferepr(object):
|
|
441
|
+
"""Like repr() but recursive references are marked as <Recursion ...>."""
|
|
442
|
+
r = _safe_repr(object, v'new Map()', None, 0, True)
|
|
443
|
+
return r[0]
|
|
444
|
+
|
|
445
|
+
|
|
446
|
+
def isreadable(object):
|
|
447
|
+
"""True if pformat(object) is readable by eval()."""
|
|
448
|
+
r = _safe_repr(object, v'new Map()', None, 0, True)
|
|
449
|
+
return r[1] and not r[2]
|
|
450
|
+
|
|
451
|
+
|
|
452
|
+
def isrecursive(object):
|
|
453
|
+
"""True if object contains any recursive references."""
|
|
454
|
+
r = _safe_repr(object, v'new Map()', None, 0, True)
|
|
455
|
+
return r[2]
|
package/src/lib/random.pyj
CHANGED
|
@@ -1,118 +1,118 @@
|
|
|
1
|
-
###########################################################
|
|
2
|
-
# RapydScript Standard Library
|
|
3
|
-
# Author: Alexander Tsepkov
|
|
4
|
-
# Copyright 2013 Pyjeon Software LLC
|
|
5
|
-
# License: Apache License 2.0
|
|
6
|
-
# This library is covered under Apache license, so that
|
|
7
|
-
# you can distribute it with your RapydScript applications.
|
|
8
|
-
###########################################################
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
# basic implementation of Python's 'random' library
|
|
12
|
-
|
|
13
|
-
# JavaScript's Math.random() does not allow seeding its random generator, to bypass that, this module implements its own
|
|
14
|
-
# version that can be seeded. I decided on RC4 algorithm for this.
|
|
15
|
-
|
|
16
|
-
# please don't mess with this from the outside
|
|
17
|
-
|
|
18
|
-
ρσ_seed_state = {
|
|
19
|
-
'key': [],
|
|
20
|
-
'key_i': 0,
|
|
21
|
-
'key_j': 0
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
ρσ_get_random_byte = def():
|
|
25
|
-
ρσ_seed_state.key_i = (ρσ_seed_state.key_i + 1) % 256
|
|
26
|
-
ρσ_seed_state.key_j = (ρσ_seed_state.key_j + ρσ_seed_state.key[ρσ_seed_state.key_i]) % 256
|
|
27
|
-
ρσ_seed_state.key[ρσ_seed_state.key_i], ρσ_seed_state.key[ρσ_seed_state.key_j] = \
|
|
28
|
-
ρσ_seed_state.key[ρσ_seed_state.key_j], ρσ_seed_state.key[ρσ_seed_state.key_i]
|
|
29
|
-
return ρσ_seed_state.key[(ρσ_seed_state.key[ρσ_seed_state.key_i] + \
|
|
30
|
-
ρσ_seed_state.key[ρσ_seed_state.key_j]) % 256]
|
|
31
|
-
|
|
32
|
-
def seed(x=Date().getTime()):
|
|
33
|
-
ρσ_seed_state.key_i = ρσ_seed_state.key_j = 0
|
|
34
|
-
if jstype(x) is 'number':
|
|
35
|
-
x = x.toString()
|
|
36
|
-
elif jstype(x) is not 'string':
|
|
37
|
-
raise TypeError("unhashable type: '" + jstype(x) + "'")
|
|
38
|
-
for i in range(256):
|
|
39
|
-
ρσ_seed_state.key[i] = i
|
|
40
|
-
j = 0
|
|
41
|
-
for i in range(256):
|
|
42
|
-
j = (j + ρσ_seed_state.key[i] + x.charCodeAt(i % x.length)) % 256
|
|
43
|
-
ρσ_seed_state.key[i], ρσ_seed_state.key[j] = ρσ_seed_state.key[j], ρσ_seed_state.key[i]
|
|
44
|
-
seed()
|
|
45
|
-
|
|
46
|
-
def random():
|
|
47
|
-
n = 0
|
|
48
|
-
m = 1
|
|
49
|
-
for i in range(8):
|
|
50
|
-
n += ρσ_get_random_byte() * m
|
|
51
|
-
m *= 256
|
|
52
|
-
return v'n / 0x10000000000000000'
|
|
53
|
-
|
|
54
|
-
def randrange():
|
|
55
|
-
if arguments.length is 1:
|
|
56
|
-
return randbelow(int(arguments[0]))
|
|
57
|
-
start = int(arguments[0])
|
|
58
|
-
stop = int(arguments[1])
|
|
59
|
-
if arguments.length < 3:
|
|
60
|
-
step = 1
|
|
61
|
-
else:
|
|
62
|
-
step = int(arguments[2])
|
|
63
|
-
width = stop - start
|
|
64
|
-
if step is 1:
|
|
65
|
-
if width > 0:
|
|
66
|
-
return start + randbelow(width)
|
|
67
|
-
raise ValueError("empty range for randrange()")
|
|
68
|
-
if step > 0:
|
|
69
|
-
n = (width + step - 1) // step
|
|
70
|
-
elif step < 0:
|
|
71
|
-
n = (width + step + 1) // step
|
|
72
|
-
else:
|
|
73
|
-
raise ValueError("zero step for randrange()")
|
|
74
|
-
if n <= 0:
|
|
75
|
-
raise ValueError(f"empty range in randrange({start}, {stop}, {step})")
|
|
76
|
-
return start + step * randbelow(n)
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
def randint(a, b):
|
|
80
|
-
return int(random()*(b-a+1) + a)
|
|
81
|
-
|
|
82
|
-
def uniform(a, b):
|
|
83
|
-
return random()*(b-a) + a
|
|
84
|
-
|
|
85
|
-
def randbelow(n):
|
|
86
|
-
return Math.floor(random()*n)
|
|
87
|
-
|
|
88
|
-
def choice(seq):
|
|
89
|
-
if seq.length > 0:
|
|
90
|
-
return seq[randbelow(seq.length)]
|
|
91
|
-
else:
|
|
92
|
-
raise IndexError()
|
|
93
|
-
|
|
94
|
-
# uses Fisher-Yates algorithm to shuffle an array
|
|
95
|
-
def shuffle(x, random_f=random):
|
|
96
|
-
for i in range(x.length):
|
|
97
|
-
j = Math.floor(random_f() * (i+1))
|
|
98
|
-
x[i], x[j] = x[j], x[i]
|
|
99
|
-
return x
|
|
100
|
-
|
|
101
|
-
# similar to shuffle, but only shuffles a subset and creates a copy
|
|
102
|
-
def sample(population, k):
|
|
103
|
-
x = population.slice()
|
|
104
|
-
for i in range(population.length-1, population.length-k-1, -1):
|
|
105
|
-
j = Math.floor(random() * (i+1))
|
|
106
|
-
x[i], x[j] = x[j], x[i]
|
|
107
|
-
return x.slice(population.length-k)
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
#import stdlib
|
|
111
|
-
#a = range(50)
|
|
112
|
-
#random.seed(5)
|
|
113
|
-
#print(random.choice(a))
|
|
114
|
-
#print(random.shuffle(a))
|
|
115
|
-
#print(random.randrange(10))
|
|
116
|
-
#print(random.randint(1,5))
|
|
117
|
-
#print(random.uniform(1,5))
|
|
118
|
-
#print(random.sample(range(20),5))
|
|
1
|
+
###########################################################
|
|
2
|
+
# RapydScript Standard Library
|
|
3
|
+
# Author: Alexander Tsepkov
|
|
4
|
+
# Copyright 2013 Pyjeon Software LLC
|
|
5
|
+
# License: Apache License 2.0
|
|
6
|
+
# This library is covered under Apache license, so that
|
|
7
|
+
# you can distribute it with your RapydScript applications.
|
|
8
|
+
###########################################################
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
# basic implementation of Python's 'random' library
|
|
12
|
+
|
|
13
|
+
# JavaScript's Math.random() does not allow seeding its random generator, to bypass that, this module implements its own
|
|
14
|
+
# version that can be seeded. I decided on RC4 algorithm for this.
|
|
15
|
+
|
|
16
|
+
# please don't mess with this from the outside
|
|
17
|
+
|
|
18
|
+
ρσ_seed_state = {
|
|
19
|
+
'key': [],
|
|
20
|
+
'key_i': 0,
|
|
21
|
+
'key_j': 0
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
ρσ_get_random_byte = def():
|
|
25
|
+
ρσ_seed_state.key_i = (ρσ_seed_state.key_i + 1) % 256
|
|
26
|
+
ρσ_seed_state.key_j = (ρσ_seed_state.key_j + ρσ_seed_state.key[ρσ_seed_state.key_i]) % 256
|
|
27
|
+
ρσ_seed_state.key[ρσ_seed_state.key_i], ρσ_seed_state.key[ρσ_seed_state.key_j] = \
|
|
28
|
+
ρσ_seed_state.key[ρσ_seed_state.key_j], ρσ_seed_state.key[ρσ_seed_state.key_i]
|
|
29
|
+
return ρσ_seed_state.key[(ρσ_seed_state.key[ρσ_seed_state.key_i] + \
|
|
30
|
+
ρσ_seed_state.key[ρσ_seed_state.key_j]) % 256]
|
|
31
|
+
|
|
32
|
+
def seed(x=Date().getTime()):
|
|
33
|
+
ρσ_seed_state.key_i = ρσ_seed_state.key_j = 0
|
|
34
|
+
if jstype(x) is 'number':
|
|
35
|
+
x = x.toString()
|
|
36
|
+
elif jstype(x) is not 'string':
|
|
37
|
+
raise TypeError("unhashable type: '" + jstype(x) + "'")
|
|
38
|
+
for i in range(256):
|
|
39
|
+
ρσ_seed_state.key[i] = i
|
|
40
|
+
j = 0
|
|
41
|
+
for i in range(256):
|
|
42
|
+
j = (j + ρσ_seed_state.key[i] + x.charCodeAt(i % x.length)) % 256
|
|
43
|
+
ρσ_seed_state.key[i], ρσ_seed_state.key[j] = ρσ_seed_state.key[j], ρσ_seed_state.key[i]
|
|
44
|
+
seed()
|
|
45
|
+
|
|
46
|
+
def random():
|
|
47
|
+
n = 0
|
|
48
|
+
m = 1
|
|
49
|
+
for i in range(8):
|
|
50
|
+
n += ρσ_get_random_byte() * m
|
|
51
|
+
m *= 256
|
|
52
|
+
return v'n / 0x10000000000000000'
|
|
53
|
+
|
|
54
|
+
def randrange():
|
|
55
|
+
if arguments.length is 1:
|
|
56
|
+
return randbelow(int(arguments[0]))
|
|
57
|
+
start = int(arguments[0])
|
|
58
|
+
stop = int(arguments[1])
|
|
59
|
+
if arguments.length < 3:
|
|
60
|
+
step = 1
|
|
61
|
+
else:
|
|
62
|
+
step = int(arguments[2])
|
|
63
|
+
width = stop - start
|
|
64
|
+
if step is 1:
|
|
65
|
+
if width > 0:
|
|
66
|
+
return start + randbelow(width)
|
|
67
|
+
raise ValueError("empty range for randrange()")
|
|
68
|
+
if step > 0:
|
|
69
|
+
n = (width + step - 1) // step
|
|
70
|
+
elif step < 0:
|
|
71
|
+
n = (width + step + 1) // step
|
|
72
|
+
else:
|
|
73
|
+
raise ValueError("zero step for randrange()")
|
|
74
|
+
if n <= 0:
|
|
75
|
+
raise ValueError(f"empty range in randrange({start}, {stop}, {step})")
|
|
76
|
+
return start + step * randbelow(n)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def randint(a, b):
|
|
80
|
+
return int(random()*(b-a+1) + a)
|
|
81
|
+
|
|
82
|
+
def uniform(a, b):
|
|
83
|
+
return random()*(b-a) + a
|
|
84
|
+
|
|
85
|
+
def randbelow(n):
|
|
86
|
+
return Math.floor(random()*n)
|
|
87
|
+
|
|
88
|
+
def choice(seq):
|
|
89
|
+
if seq.length > 0:
|
|
90
|
+
return seq[randbelow(seq.length)]
|
|
91
|
+
else:
|
|
92
|
+
raise IndexError()
|
|
93
|
+
|
|
94
|
+
# uses Fisher-Yates algorithm to shuffle an array
|
|
95
|
+
def shuffle(x, random_f=random):
|
|
96
|
+
for i in range(x.length):
|
|
97
|
+
j = Math.floor(random_f() * (i+1))
|
|
98
|
+
x[i], x[j] = x[j], x[i]
|
|
99
|
+
return x
|
|
100
|
+
|
|
101
|
+
# similar to shuffle, but only shuffles a subset and creates a copy
|
|
102
|
+
def sample(population, k):
|
|
103
|
+
x = population.slice()
|
|
104
|
+
for i in range(population.length-1, population.length-k-1, -1):
|
|
105
|
+
j = Math.floor(random() * (i+1))
|
|
106
|
+
x[i], x[j] = x[j], x[i]
|
|
107
|
+
return x.slice(population.length-k)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
#import stdlib
|
|
111
|
+
#a = range(50)
|
|
112
|
+
#random.seed(5)
|
|
113
|
+
#print(random.choice(a))
|
|
114
|
+
#print(random.shuffle(a))
|
|
115
|
+
#print(random.randrange(10))
|
|
116
|
+
#print(random.randint(1,5))
|
|
117
|
+
#print(random.uniform(1,5))
|
|
118
|
+
#print(random.sample(range(20),5))
|