rapydscript-ns 0.9.1 → 0.9.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/CHANGELOG.md +22 -1
  2. package/PYTHON_GAPS.md +420 -0
  3. package/README.md +154 -30
  4. package/TODO.md +22 -7
  5. package/language-service/index.js +241 -12
  6. package/language-service/language-service.d.ts +1 -1
  7. package/memory/project_string_impl.md +43 -0
  8. package/package.json +6 -2
  9. package/release/baselib-plain-pretty.js +248 -38
  10. package/release/baselib-plain-ugly.js +8 -8
  11. package/release/compiler.js +821 -305
  12. package/release/signatures.json +15 -15
  13. package/src/ast.pyj +4 -1
  14. package/src/baselib-builtins.pyj +56 -2
  15. package/src/baselib-containers.pyj +2 -0
  16. package/src/baselib-errors.pyj +7 -3
  17. package/src/baselib-internal.pyj +51 -6
  18. package/src/baselib-str.pyj +5 -3
  19. package/src/lib/asyncio.pyj +534 -0
  20. package/src/lib/base64.pyj +399 -0
  21. package/src/lib/bisect.pyj +73 -0
  22. package/src/lib/collections.pyj +1 -1
  23. package/src/lib/csv.pyj +494 -0
  24. package/src/lib/heapq.pyj +98 -0
  25. package/src/lib/html.pyj +382 -0
  26. package/src/lib/http/__init__.pyj +98 -0
  27. package/src/lib/http/client.pyj +304 -0
  28. package/src/lib/http/cookies.pyj +236 -0
  29. package/src/lib/logging.pyj +672 -0
  30. package/src/lib/pythonize.pyj +1 -1
  31. package/src/lib/string.pyj +357 -0
  32. package/src/lib/textwrap.pyj +329 -0
  33. package/src/lib/urllib/__init__.pyj +14 -0
  34. package/src/lib/urllib/error.pyj +66 -0
  35. package/src/lib/urllib/parse.pyj +475 -0
  36. package/src/lib/urllib/request.pyj +86 -0
  37. package/src/monaco-language-service/analyzer.js +5 -2
  38. package/src/monaco-language-service/completions.js +26 -0
  39. package/src/monaco-language-service/diagnostics.js +204 -5
  40. package/src/monaco-language-service/index.js +2 -2
  41. package/src/monaco-language-service/scope.js +1 -0
  42. package/src/output/functions.pyj +152 -6
  43. package/src/output/loops.pyj +26 -2
  44. package/src/output/modules.pyj +1 -1
  45. package/src/output/operators.pyj +15 -0
  46. package/src/output/stream.pyj +0 -1
  47. package/src/parse.pyj +80 -17
  48. package/src/tokenizer.pyj +1 -1
  49. package/test/async_generators.pyj +144 -0
  50. package/test/asyncio.pyj +307 -0
  51. package/test/base64.pyj +202 -0
  52. package/test/bisect.pyj +178 -0
  53. package/test/csv.pyj +405 -0
  54. package/test/float_special.pyj +64 -0
  55. package/test/heapq.pyj +174 -0
  56. package/test/html.pyj +212 -0
  57. package/test/http.pyj +259 -0
  58. package/test/imports.pyj +7 -0
  59. package/test/logging.pyj +356 -0
  60. package/test/long.pyj +130 -0
  61. package/test/parenthesized_with.pyj +141 -0
  62. package/test/python_compat.pyj +3 -5
  63. package/test/python_modulo.pyj +76 -0
  64. package/test/python_modulo_off.pyj +21 -0
  65. package/test/str.pyj +14 -0
  66. package/test/string.pyj +245 -0
  67. package/test/textwrap.pyj +172 -0
  68. package/test/type_display.pyj +48 -0
  69. package/test/type_enforcement.pyj +164 -0
  70. package/test/unit/index.js +80 -6
  71. package/test/unit/language-service-completions.js +119 -0
  72. package/test/unit/language-service-scope.js +32 -0
  73. package/test/unit/language-service.js +128 -4
  74. package/test/unit/run-language-service.js +17 -3
  75. package/test/unit/web-repl.js +2094 -29
  76. package/test/urllib.pyj +193 -0
  77. package/tools/compile.js +1 -1
  78. package/tools/compiler.d.ts +367 -0
  79. package/tools/embedded_compiler.js +7 -7
  80. package/web-repl/main.js +1 -1
  81. package/web-repl/rapydscript.js +3 -3
  82. package/test/omit_function_metadata.pyj +0 -20
@@ -0,0 +1,494 @@
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
+ # Python-compatible csv module.
9
+ #
10
+ # Provides: reader, writer, DictReader, DictWriter,
11
+ # Dialect, excel, excel_tab, unix_dialect,
12
+ # register_dialect, unregister_dialect,
13
+ # get_dialect, list_dialects, field_size_limit,
14
+ # QUOTE_MINIMAL, QUOTE_ALL, QUOTE_NONNUMERIC, QUOTE_NONE,
15
+ # Error.
16
+ #
17
+ # Usage:
18
+ # import csv
19
+ # from io import StringIO
20
+ #
21
+ # rows = []
22
+ # for row in csv.reader(['a,b,c', '1,2,3']):
23
+ # rows.push(row)
24
+ #
25
+ # sio = StringIO()
26
+ # w = csv.writer(sio)
27
+ # w.writerow(['name', 'age'])
28
+ # w.writerow(['Alice', 30])
29
+ # print(sio.getvalue())
30
+ #
31
+ # Notes:
32
+ # - DictReader rows are returned as plain JS objects (access with row.field
33
+ # or row['field']); they are NOT ρσ_dict instances.
34
+ # - `default` is a JS reserved word; csv.writer's dflt param is irrelevant
35
+ # here, but `dialect` parameters named `default` become `dialect=` positional.
36
+ # - csv.Error shadows the native JS Error constructor if imported with
37
+ # `from csv import Error` in web-repl mode; catch via Exception instead.
38
+
39
+
40
+ QUOTE_MINIMAL = 0
41
+ QUOTE_ALL = 1
42
+ QUOTE_NONNUMERIC = 2
43
+ QUOTE_NONE = 3
44
+
45
+
46
+ class Error(Exception):
47
+ pass
48
+
49
+
50
+ # ---------------------------------------------------------------------------
51
+ # Internal JS helpers
52
+ # ---------------------------------------------------------------------------
53
+
54
+ v"""
55
+ // Convert csvfile input (string, file-like, array, or iterable) to a flat
56
+ // text string suitable for _csv_parse_text. Array inputs strip trailing
57
+ // \r/\n from each element before joining so that lines like 'a,b\n' and
58
+ // 'a,b' both produce the same row. Returns null for an empty array (signals
59
+ // zero rows, not one empty-field row).
60
+ function _csv_to_text(src) {
61
+ if (typeof src === 'string') return src;
62
+ if (src && typeof src.read === 'function') {
63
+ return String(src.read() || '');
64
+ }
65
+ var arr = null;
66
+ if (Array.isArray(src)) {
67
+ arr = src;
68
+ } else if (src && typeof src[Symbol.iterator] === 'function') {
69
+ arr = [];
70
+ var it = src[Symbol.iterator]();
71
+ var r = it.next();
72
+ while (!r.done) { arr.push(r.value); r = it.next(); }
73
+ }
74
+ if (arr !== null) {
75
+ if (arr.length === 0) return null;
76
+ var stripped = arr.map(function(s) {
77
+ s = String(s);
78
+ var end = s.length;
79
+ while (end > 0 && (s[end-1] === '\r' || s[end-1] === '\n')) end--;
80
+ return s.slice(0, end);
81
+ });
82
+ return stripped.join('\n') + '\n';
83
+ }
84
+ return String(src || '');
85
+ }
86
+
87
+ // Parse a CSV text string into an array of row arrays.
88
+ // Handles quoted fields (including multi-line), escape chars, and all
89
+ // QUOTE_* modes. Returns [] for null input (empty array source).
90
+ function _csv_parse_text(text, delimiter, quotechar, escapechar,
91
+ doublequote, skipinitialspace, quoting) {
92
+ if (text === null) return [];
93
+ var rows = [];
94
+ var field = '';
95
+ var fields = [];
96
+ var in_q = false;
97
+ var i = 0, n = text.length;
98
+
99
+ function push_field() {
100
+ if (quoting === 2) {
101
+ var f = field;
102
+ field = '';
103
+ var num = parseFloat(f);
104
+ fields.push((f.trim() !== '' && !isNaN(num) && isFinite(num)) ? num : f);
105
+ } else {
106
+ fields.push(field);
107
+ field = '';
108
+ }
109
+ }
110
+
111
+ while (i < n) {
112
+ var c = text[i];
113
+ if (in_q) {
114
+ if (quotechar && c === quotechar) {
115
+ if (doublequote && i + 1 < n && text[i+1] === quotechar) {
116
+ field += quotechar; i += 2;
117
+ } else {
118
+ in_q = false; i++;
119
+ }
120
+ } else if (escapechar && c === escapechar && i + 1 < n) {
121
+ field += text[i+1]; i += 2;
122
+ } else {
123
+ field += c; i++;
124
+ }
125
+ } else {
126
+ if (c === '\r' || c === '\n') {
127
+ push_field();
128
+ rows.push(fields);
129
+ fields = [];
130
+ i++;
131
+ if (c === '\r' && i < n && text[i] === '\n') i++;
132
+ } else if (c === delimiter) {
133
+ push_field();
134
+ i++;
135
+ if (skipinitialspace && i < n && text[i] === ' ') i++;
136
+ } else if (quotechar && c === quotechar && quoting !== 3) {
137
+ in_q = true; i++;
138
+ } else if (escapechar && c === escapechar && i + 1 < n) {
139
+ field += text[i+1]; i += 2;
140
+ } else {
141
+ field += c; i++;
142
+ }
143
+ }
144
+ }
145
+ // final row when text does not end with a newline
146
+ if (fields.length > 0 || field !== '') {
147
+ push_field();
148
+ rows.push(fields);
149
+ }
150
+ return rows;
151
+ }
152
+
153
+ // Format a single CSV field value.
154
+ function _csv_fmt_field(field, delimiter, quotechar, escapechar,
155
+ doublequote, quoting) {
156
+ var s;
157
+ if (field === null || field === undefined) s = '';
158
+ else s = String(field);
159
+
160
+ var needs_q = false;
161
+ if (quoting === 1) {
162
+ needs_q = true;
163
+ } else if (quoting === 2) {
164
+ if (typeof field !== 'number') needs_q = true;
165
+ } else if (quoting === 0) {
166
+ for (var i = 0; i < s.length; i++) {
167
+ var c = s[i];
168
+ if (c === delimiter || c === '\r' || c === '\n' ||
169
+ (quotechar && c === quotechar)) { needs_q = true; break; }
170
+ }
171
+ }
172
+
173
+ if (quoting === 3) { // QUOTE_NONE
174
+ if (!escapechar) return s;
175
+ var out = '';
176
+ for (var j = 0; j < s.length; j++) {
177
+ var ch = s[j];
178
+ if (ch === delimiter || ch === escapechar) out += escapechar;
179
+ out += ch;
180
+ }
181
+ return out;
182
+ }
183
+
184
+ if (!needs_q) return s;
185
+ var q = quotechar || '"';
186
+ var r = q;
187
+ for (var k = 0; k < s.length; k++) {
188
+ var fc = s[k];
189
+ if (fc === q) {
190
+ if (doublequote) r += q + q;
191
+ else if (escapechar) r += escapechar + q;
192
+ else r += q;
193
+ } else if (escapechar && fc === escapechar) {
194
+ r += escapechar + escapechar;
195
+ } else {
196
+ r += fc;
197
+ }
198
+ }
199
+ return r + q;
200
+ }
201
+
202
+ // Dict helpers — handle both plain JS objects and ρσ_dict (web-repl mode).
203
+ function _csv_dict_keys(d) {
204
+ if (d && d.jsmap && typeof d.jsmap.forEach === 'function') {
205
+ var ks = [];
206
+ d.jsmap.forEach(function(v, k) { ks.push(k); });
207
+ return ks;
208
+ }
209
+ return Object.keys(d || {});
210
+ }
211
+ function _csv_dict_get(d, key, dflt) {
212
+ if (d && d.jsmap && typeof d.jsmap.get === 'function') {
213
+ return d.jsmap.has(key) ? d.jsmap.get(key) : dflt;
214
+ }
215
+ if (Object.prototype.hasOwnProperty.call(d || {}, key)) return d[key];
216
+ return dflt;
217
+ }
218
+ """
219
+
220
+
221
+ # ---------------------------------------------------------------------------
222
+ # Dialect classes
223
+ # ---------------------------------------------------------------------------
224
+
225
+ class Dialect:
226
+ delimiter = ','
227
+ quotechar = '"'
228
+ escapechar = None
229
+ doublequote = True
230
+ skipinitialspace = False
231
+ lineterminator = '\r\n'
232
+ quoting = QUOTE_MINIMAL
233
+ strict = False
234
+
235
+
236
+ class excel(Dialect):
237
+ pass
238
+
239
+
240
+ class excel_tab(Dialect):
241
+ delimiter = '\t'
242
+
243
+
244
+ class unix_dialect(Dialect):
245
+ lineterminator = '\n'
246
+ quoting = QUOTE_ALL
247
+
248
+
249
+ # ---------------------------------------------------------------------------
250
+ # Dialect registry
251
+ # ---------------------------------------------------------------------------
252
+
253
+ _dialects = {}
254
+ _dialects['excel'] = excel()
255
+ _dialects['excel-tab'] = excel_tab()
256
+ _dialects['unix'] = unix_dialect()
257
+
258
+
259
+ def _build_dialect(dialect, delimiter, quotechar, escapechar, doublequote,
260
+ skipinitialspace, lineterminator, quoting, strict):
261
+ if jstype(dialect) is 'string':
262
+ if dialect not in _dialects:
263
+ raise Error('unknown dialect: ' + dialect)
264
+ tmpl = _dialects[dialect]
265
+ elif dialect is None:
266
+ tmpl = _dialects['excel']
267
+ elif jstype(dialect) is 'function':
268
+ tmpl = dialect()
269
+ else:
270
+ tmpl = dialect
271
+ d = Dialect()
272
+ d.delimiter = tmpl.delimiter
273
+ d.quotechar = tmpl.quotechar
274
+ d.escapechar = tmpl.escapechar
275
+ d.doublequote = tmpl.doublequote
276
+ d.skipinitialspace = tmpl.skipinitialspace
277
+ d.lineterminator = tmpl.lineterminator
278
+ d.quoting = tmpl.quoting
279
+ d.strict = tmpl.strict
280
+ if delimiter is not None: d.delimiter = delimiter
281
+ if quotechar is not None: d.quotechar = quotechar
282
+ if escapechar is not None: d.escapechar = escapechar
283
+ if doublequote is not None: d.doublequote = doublequote
284
+ if skipinitialspace is not None: d.skipinitialspace = skipinitialspace
285
+ if lineterminator is not None: d.lineterminator = lineterminator
286
+ if quoting is not None: d.quoting = quoting
287
+ if strict is not None: d.strict = strict
288
+ return d
289
+
290
+
291
+ # ---------------------------------------------------------------------------
292
+ # Reader
293
+ # ---------------------------------------------------------------------------
294
+
295
+ class _Reader:
296
+ def __init__(self, csvfile, d):
297
+ self.dialect = d
298
+ self.line_num = 0
299
+ self._index = 0
300
+ self._rows = _csv_parse_text(
301
+ _csv_to_text(csvfile),
302
+ d.delimiter, d.quotechar, d.escapechar,
303
+ d.doublequote, d.skipinitialspace, d.quoting
304
+ )
305
+
306
+ def __iter__(self):
307
+ return self
308
+
309
+ def next(self):
310
+ if self._index >= self._rows.length:
311
+ return {'value': undefined, 'done': True}
312
+ row = self._rows[self._index]
313
+ self._index += 1
314
+ self.line_num = self._index
315
+ return {'value': row, 'done': False}
316
+
317
+ def __next__(self):
318
+ r = self.next()
319
+ if r.done:
320
+ raise StopIteration()
321
+ return r.value
322
+
323
+
324
+ def reader(csvfile, dialect='excel', delimiter=None, quotechar=None,
325
+ escapechar=None, doublequote=None, skipinitialspace=None,
326
+ lineterminator=None, quoting=None, strict=None):
327
+ d = _build_dialect(dialect, delimiter, quotechar, escapechar, doublequote,
328
+ skipinitialspace, lineterminator, quoting, strict)
329
+ return _Reader(csvfile, d)
330
+
331
+
332
+ # ---------------------------------------------------------------------------
333
+ # Writer
334
+ # ---------------------------------------------------------------------------
335
+
336
+ class _Writer:
337
+ def __init__(self, csvfile, d):
338
+ self.dialect = d
339
+ self._file = csvfile
340
+
341
+ def writerow(self, row):
342
+ d = self.dialect
343
+ parts = []
344
+ for field in row:
345
+ parts.push(_csv_fmt_field(field, d.delimiter, d.quotechar,
346
+ d.escapechar, d.doublequote, d.quoting))
347
+ self._file.write(parts.join(d.delimiter) + d.lineterminator)
348
+
349
+ def writerows(self, rows):
350
+ for row in rows:
351
+ self.writerow(row)
352
+
353
+
354
+ def writer(csvfile, dialect='excel', delimiter=None, quotechar=None,
355
+ escapechar=None, doublequote=None, skipinitialspace=None,
356
+ lineterminator=None, quoting=None, strict=None):
357
+ d = _build_dialect(dialect, delimiter, quotechar, escapechar, doublequote,
358
+ skipinitialspace, lineterminator, quoting, strict)
359
+ return _Writer(csvfile, d)
360
+
361
+
362
+ # ---------------------------------------------------------------------------
363
+ # DictReader
364
+ # ---------------------------------------------------------------------------
365
+
366
+ class DictReader:
367
+ def __init__(self, f, fieldnames=None, restkey=None, restval=None,
368
+ dialect='excel', delimiter=None, quotechar=None,
369
+ escapechar=None, doublequote=None, skipinitialspace=None,
370
+ lineterminator=None, quoting=None, strict=None):
371
+ self._reader = reader(f, dialect, delimiter, quotechar, escapechar,
372
+ doublequote, skipinitialspace, lineterminator,
373
+ quoting, strict)
374
+ self.fieldnames = fieldnames
375
+ self.restkey = restkey if restkey is not None else 'EXTRA'
376
+ self.restval = restval
377
+ self.dialect = self._reader.dialect
378
+ self.line_num = 0
379
+
380
+ def _ensure_fieldnames(self):
381
+ if self.fieldnames is None:
382
+ try:
383
+ self.fieldnames = self._reader.__next__()
384
+ except StopIteration:
385
+ self.fieldnames = []
386
+
387
+ def __iter__(self):
388
+ return self
389
+
390
+ def next(self):
391
+ self._ensure_fieldnames()
392
+ try:
393
+ row = self._reader.__next__()
394
+ except StopIteration:
395
+ return {'value': undefined, 'done': True}
396
+ self.line_num = self._reader.line_num
397
+ fields = self.fieldnames
398
+ d = {}
399
+ for i in range(fields.length):
400
+ d[fields[i]] = row[i] if i < row.length else self.restval
401
+ if row.length > fields.length:
402
+ d[self.restkey] = row.slice(fields.length)
403
+ return {'value': d, 'done': False}
404
+
405
+ def __next__(self):
406
+ r = self.next()
407
+ if r.done:
408
+ raise StopIteration()
409
+ return r.value
410
+
411
+
412
+ # ---------------------------------------------------------------------------
413
+ # DictWriter
414
+ # ---------------------------------------------------------------------------
415
+
416
+ class DictWriter:
417
+ def __init__(self, f, fieldnames, restval='', extrasaction='raise',
418
+ dialect='excel', delimiter=None, quotechar=None,
419
+ escapechar=None, doublequote=None, skipinitialspace=None,
420
+ lineterminator=None, quoting=None, strict=None):
421
+ self.fieldnames = fieldnames
422
+ self.restval = restval
423
+ self.extrasaction = extrasaction
424
+ self._writer = writer(f, dialect, delimiter, quotechar, escapechar,
425
+ doublequote, skipinitialspace, lineterminator,
426
+ quoting, strict)
427
+ self.dialect = self._writer.dialect
428
+
429
+ def writeheader(self):
430
+ self._writer.writerow(self.fieldnames)
431
+
432
+ def writerow(self, rowdict):
433
+ row = []
434
+ fields = self.fieldnames
435
+ restval = self.restval
436
+ v"""
437
+ if (this.extrasaction === 'raise') {
438
+ var _dkeys = _csv_dict_keys(rowdict);
439
+ for (var _i = 0; _i < _dkeys.length; _i++) {
440
+ if (fields.indexOf(_dkeys[_i]) < 0) {
441
+ throw new ValueError(
442
+ "dict contains fields not in fieldnames: '" + _dkeys[_i] + "'");
443
+ }
444
+ }
445
+ }
446
+ for (var _j = 0; _j < fields.length; _j++) {
447
+ row.push(_csv_dict_get(rowdict, fields[_j], restval));
448
+ }
449
+ """
450
+ self._writer.writerow(row)
451
+
452
+ def writerows(self, rowdicts):
453
+ for rowdict in rowdicts:
454
+ self.writerow(rowdict)
455
+
456
+
457
+ # ---------------------------------------------------------------------------
458
+ # Dialect management
459
+ # ---------------------------------------------------------------------------
460
+
461
+ def register_dialect(name, dialect=None, delimiter=None, quotechar=None,
462
+ escapechar=None, doublequote=None, skipinitialspace=None,
463
+ lineterminator=None, quoting=None, strict=None):
464
+ base = excel if dialect is None else dialect
465
+ d = _build_dialect(base, delimiter, quotechar, escapechar, doublequote,
466
+ skipinitialspace, lineterminator, quoting, strict)
467
+ _dialects[name] = d
468
+
469
+
470
+ def unregister_dialect(name):
471
+ if name not in _dialects:
472
+ raise Error('unknown dialect: ' + name)
473
+ v'delete _dialects[name]'
474
+
475
+
476
+ def get_dialect(name):
477
+ if name not in _dialects:
478
+ raise Error('unknown dialect: ' + name)
479
+ return _dialects[name]
480
+
481
+
482
+ def list_dialects():
483
+ return Object.keys(_dialects)
484
+
485
+
486
+ _field_size_limit_val = 131072
487
+
488
+
489
+ def field_size_limit(new_limit=None):
490
+ global _field_size_limit_val
491
+ old = _field_size_limit_val
492
+ if new_limit is not None:
493
+ _field_size_limit_val = new_limit
494
+ return old
@@ -0,0 +1,98 @@
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 'heapq' module.
10
+ # Min-heap (priority queue) operations on lists.
11
+ #
12
+ # The heap invariant: heap[k] <= heap[2*k+1] and heap[k] <= heap[2*k+2].
13
+ # Algorithms ported from CPython's heapq.py.
14
+
15
+
16
+ def _siftdown(heap, startpos, pos):
17
+ newitem = heap[pos]
18
+ while pos > startpos:
19
+ parentpos = (pos - 1) >> 1
20
+ parent = heap[parentpos]
21
+ if newitem < parent:
22
+ heap[pos] = parent
23
+ pos = parentpos
24
+ else:
25
+ break
26
+ heap[pos] = newitem
27
+
28
+
29
+ def _siftup(heap, pos):
30
+ endpos = heap.length
31
+ startpos = pos
32
+ newitem = heap[pos]
33
+ childpos = 2 * pos + 1
34
+ while childpos < endpos:
35
+ rightpos = childpos + 1
36
+ if rightpos < endpos and heap[childpos] >= heap[rightpos]:
37
+ childpos = rightpos
38
+ heap[pos] = heap[childpos]
39
+ pos = childpos
40
+ childpos = 2 * pos + 1
41
+ heap[pos] = newitem
42
+ _siftdown(heap, startpos, pos)
43
+
44
+
45
+ def heappush(heap, item):
46
+ heap.push(item)
47
+ _siftdown(heap, 0, heap.length - 1)
48
+
49
+
50
+ def heappop(heap):
51
+ if heap.length == 0:
52
+ raise IndexError('index out of range')
53
+ lastelt = heap.pop()
54
+ if heap.length > 0:
55
+ returnitem = heap[0]
56
+ heap[0] = lastelt
57
+ _siftup(heap, 0)
58
+ return returnitem
59
+ return lastelt
60
+
61
+
62
+ def heapreplace(heap, item):
63
+ if heap.length == 0:
64
+ raise IndexError('index out of range')
65
+ returnitem = heap[0]
66
+ heap[0] = item
67
+ _siftup(heap, 0)
68
+ return returnitem
69
+
70
+
71
+ def heappushpop(heap, item):
72
+ if heap.length > 0 and heap[0] < item:
73
+ tmp = heap[0]
74
+ heap[0] = item
75
+ item = tmp
76
+ _siftup(heap, 0)
77
+ return item
78
+
79
+
80
+ def heapify(x):
81
+ i = Math.floor(x.length / 2) - 1
82
+ while i >= 0:
83
+ _siftup(x, i)
84
+ i -= 1
85
+
86
+
87
+ def nsmallest(n, iterable, key=None):
88
+ if n <= 0:
89
+ return []
90
+ result = sorted(iterable, key=key)
91
+ return result[:n]
92
+
93
+
94
+ def nlargest(n, iterable, key=None):
95
+ if n <= 0:
96
+ return []
97
+ result = sorted(iterable, key=key, reverse=True)
98
+ return result[:n]