rapydscript-ns 0.8.3 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/README.md +1351 -141
  3. package/TODO.md +12 -6
  4. package/language-service/index.js +184 -26
  5. package/package.json +1 -1
  6. package/release/baselib-plain-pretty.js +5895 -1928
  7. package/release/baselib-plain-ugly.js +140 -3
  8. package/release/compiler.js +16282 -5408
  9. package/release/signatures.json +25 -22
  10. package/src/ast.pyj +94 -1
  11. package/src/baselib-builtins.pyj +362 -3
  12. package/src/baselib-bytes.pyj +664 -0
  13. package/src/baselib-containers.pyj +99 -0
  14. package/src/baselib-errors.pyj +45 -1
  15. package/src/baselib-internal.pyj +346 -49
  16. package/src/baselib-itertools.pyj +17 -4
  17. package/src/baselib-str.pyj +46 -4
  18. package/src/lib/abc.pyj +317 -0
  19. package/src/lib/copy.pyj +120 -0
  20. package/src/lib/dataclasses.pyj +532 -0
  21. package/src/lib/enum.pyj +125 -0
  22. package/src/lib/pythonize.pyj +1 -1
  23. package/src/lib/re.pyj +35 -1
  24. package/src/lib/react.pyj +74 -0
  25. package/src/lib/typing.pyj +577 -0
  26. package/src/monaco-language-service/builtins.js +19 -4
  27. package/src/monaco-language-service/diagnostics.js +40 -19
  28. package/src/output/classes.pyj +161 -25
  29. package/src/output/codegen.pyj +16 -2
  30. package/src/output/exceptions.pyj +97 -1
  31. package/src/output/functions.pyj +87 -5
  32. package/src/output/jsx.pyj +164 -0
  33. package/src/output/literals.pyj +28 -2
  34. package/src/output/loops.pyj +5 -2
  35. package/src/output/modules.pyj +1 -1
  36. package/src/output/operators.pyj +108 -36
  37. package/src/output/statements.pyj +2 -2
  38. package/src/output/stream.pyj +1 -0
  39. package/src/parse.pyj +496 -128
  40. package/src/tokenizer.pyj +38 -4
  41. package/test/abc.pyj +291 -0
  42. package/test/arithmetic_nostrict.pyj +88 -0
  43. package/test/arithmetic_types.pyj +169 -0
  44. package/test/baselib.pyj +91 -0
  45. package/test/bytes.pyj +467 -0
  46. package/test/classes.pyj +1 -0
  47. package/test/comparison_ops.pyj +173 -0
  48. package/test/dataclasses.pyj +253 -0
  49. package/test/enum.pyj +134 -0
  50. package/test/eval_exec.pyj +56 -0
  51. package/test/format.pyj +148 -0
  52. package/test/object.pyj +64 -0
  53. package/test/python_compat.pyj +17 -15
  54. package/test/python_features.pyj +89 -21
  55. package/test/regexp.pyj +29 -1
  56. package/test/tuples.pyj +96 -0
  57. package/test/typing.pyj +469 -0
  58. package/test/unit/index.js +2292 -70
  59. package/test/unit/language-service.js +674 -4
  60. package/test/unit/web-repl.js +1106 -0
  61. package/test/vars_locals_globals.pyj +94 -0
  62. package/tools/cli.js +11 -0
  63. package/tools/compile.js +5 -0
  64. package/tools/embedded_compiler.js +15 -4
  65. package/tools/lint.js +16 -19
  66. package/tools/repl.js +1 -1
  67. package/web-repl/env.js +122 -0
  68. package/web-repl/main.js +1 -3
  69. package/web-repl/rapydscript.js +125 -3
  70. package/PYTHON_DIFFERENCES_REPORT.md +0 -291
  71. package/PYTHON_FEATURE_COVERAGE.md +0 -200
  72. package/hack_demo.pyj +0 -112
@@ -0,0 +1,664 @@
1
+ # vim:fileencoding=utf-8
2
+ # License: BSD
3
+
4
+ # globals: exports, console, ρσ_iterator_symbol, ρσ_arraylike, ρσ_str, ρσ_slice
5
+
6
+ # ---------------------------------------------------------------------------
7
+ # Encoding helpers
8
+ # ---------------------------------------------------------------------------
9
+
10
+ def ρσ_bytes_utf8_encode(s):
11
+ if v'typeof TextEncoder !== "undefined"':
12
+ return v'Array.from(new TextEncoder().encode(s))'
13
+ out = []
14
+ for v'var i = 0; i < s.length; i++':
15
+ c = s.charCodeAt(i)
16
+ if c < 0x80:
17
+ out.push(c)
18
+ elif c < 0x800:
19
+ out.push(0xC0 | (c >> 6))
20
+ out.push(0x80 | (c & 0x3F))
21
+ elif c >= 0xD800 and c <= 0xDBFF:
22
+ i += 1
23
+ c2 = s.charCodeAt(i)
24
+ cp = 0x10000 + ((c - 0xD800) << 10) + (c2 - 0xDC00)
25
+ out.push(0xF0 | (cp >> 18))
26
+ out.push(0x80 | ((cp >> 12) & 0x3F))
27
+ out.push(0x80 | ((cp >> 6) & 0x3F))
28
+ out.push(0x80 | (cp & 0x3F))
29
+ else:
30
+ out.push(0xE0 | (c >> 12))
31
+ out.push(0x80 | ((c >> 6) & 0x3F))
32
+ out.push(0x80 | (c & 0x3F))
33
+ return out
34
+
35
+ def ρσ_bytes_utf8_decode(data):
36
+ if v'typeof TextDecoder !== "undefined"':
37
+ return v'new TextDecoder("utf-8").decode(new Uint8Array(data))'
38
+ out = []
39
+ i = 0
40
+ while i < data.length:
41
+ b = data[i]
42
+ if b < 0x80:
43
+ out.push(String.fromCharCode(b))
44
+ i += 1
45
+ elif b < 0xE0:
46
+ cp = ((b & 0x1F) << 6) | (data[i + 1] & 0x3F)
47
+ out.push(String.fromCharCode(cp))
48
+ i += 2
49
+ elif b < 0xF0:
50
+ cp = ((b & 0x0F) << 12) | ((data[i + 1] & 0x3F) << 6) | (data[i + 2] & 0x3F)
51
+ out.push(String.fromCharCode(cp))
52
+ i += 3
53
+ else:
54
+ cp = ((b & 0x07) << 18) | ((data[i + 1] & 0x3F) << 12) | ((data[i + 2] & 0x3F) << 6) | (data[i + 3] & 0x3F)
55
+ cp -= 0x10000
56
+ out.push(String.fromCharCode(0xD800 + (cp >> 10)))
57
+ out.push(String.fromCharCode(0xDC00 + (cp & 0x3FF)))
58
+ i += 4
59
+ return out.join('')
60
+
61
+ def ρσ_bytes_latin1_encode(s):
62
+ out = []
63
+ for v'var i = 0; i < s.length; i++':
64
+ c = s.charCodeAt(i)
65
+ if c > 255:
66
+ raise UnicodeEncodeError('latin-1', s, i, i + 1, 'ordinal not in range(256)')
67
+ out.push(c)
68
+ return out
69
+
70
+ def ρσ_bytes_latin1_decode(data):
71
+ chars = []
72
+ for v'var i = 0; i < data.length; i++':
73
+ chars.push(String.fromCharCode(data[i]))
74
+ return chars.join('')
75
+
76
+ def ρσ_bytes_from_source(source, encoding, errors):
77
+ data = []
78
+ if arguments.length is 0 or source is None or source is undefined:
79
+ pass # empty bytes
80
+ elif jstype(source) is 'number':
81
+ n = source | 0
82
+ if n < 0:
83
+ raise ValueError('negative count')
84
+ for v'var i = 0; i < n; i++':
85
+ data.push(0)
86
+ elif jstype(source) is 'string':
87
+ enc = (encoding or 'utf-8').toLowerCase().replace(/-|_/g, '')
88
+ if enc is 'utf8':
89
+ data = ρσ_bytes_utf8_encode(source)
90
+ elif enc is 'latin1' or enc is 'iso88591' or enc is 'ascii':
91
+ data = ρσ_bytes_latin1_encode(source)
92
+ else:
93
+ raise LookupError('unknown encoding: ' + (encoding or 'utf-8'))
94
+ elif v'source instanceof ρσ_bytes' or v'source instanceof ρσ_bytearray':
95
+ data = source._data.slice()
96
+ elif v'source instanceof Uint8Array' or v'source instanceof Int8Array':
97
+ for v'var i = 0; i < source.length; i++':
98
+ data.push(source[i] & 0xFF)
99
+ elif ρσ_arraylike(source) or Array.isArray(source):
100
+ for x in source:
101
+ b = x | 0
102
+ if b < 0 or b > 255:
103
+ raise ValueError('bytes must be in range(0, 256)')
104
+ data.push(b)
105
+ elif jstype(source[ρσ_iterator_symbol]) is 'function':
106
+ iterator = source[ρσ_iterator_symbol]()
107
+ result = iterator.next()
108
+ while not result.done:
109
+ b = result.value | 0
110
+ if b < 0 or b > 255:
111
+ raise ValueError('bytes must be in range(0, 256)')
112
+ data.push(b)
113
+ result = iterator.next()
114
+ else:
115
+ raise TypeError("cannot convert '" + jstype(source) + "' object to bytes-like object")
116
+ return data
117
+
118
+ # ---------------------------------------------------------------------------
119
+ # Index sync helper — sets numeric properties on the object so that
120
+ # plain JS `obj[i]` access (used when the subscript is a literal number in
121
+ # the compiler output) returns the correct byte value. Also sets .length so
122
+ # that the negative-index arithmetic in print_getitem works correctly.
123
+ # ---------------------------------------------------------------------------
124
+
125
+ def ρσ_bytes_sync(obj):
126
+ data = obj._data
127
+ old_len = obj.length | 0
128
+ new_len = data.length
129
+ # Remove stale numeric properties beyond the new length
130
+ for v'var i = new_len; i < old_len; i++':
131
+ v'delete obj[i]'
132
+ # Set all current indices
133
+ for v'var i = 0; i < new_len; i++':
134
+ obj[i] = data[i]
135
+ obj.length = new_len
136
+
137
+ # ---------------------------------------------------------------------------
138
+ # Shared helper — search for needle (plain array) in haystack (plain array)
139
+ # starting at offset `start`. Returns index or -1.
140
+ # ---------------------------------------------------------------------------
141
+
142
+ def ρσ_bytes_find(haystack, needle, start):
143
+ hl = haystack.length
144
+ nl = needle.length
145
+ if nl is 0:
146
+ return start
147
+ for v'var i = start; i <= hl - nl; i++':
148
+ ok = True
149
+ for v'var j = 0; j < nl; j++':
150
+ if haystack[i + j] is not needle[j]:
151
+ ok = False
152
+ break
153
+ if ok:
154
+ return i
155
+ return -1
156
+
157
+ # ---------------------------------------------------------------------------
158
+ # bytes — immutable sequence of integers in 0..255
159
+ # ---------------------------------------------------------------------------
160
+
161
+ class ρσ_bytes:
162
+ def __init__(self, source, encoding, errors):
163
+ self._data = ρσ_bytes_from_source.apply(None, arguments)
164
+ ρσ_bytes_sync(self)
165
+
166
+
167
+ def __len__(self):
168
+ return self._data.length
169
+
170
+ def __getitem__(self, key):
171
+ if v'key instanceof ρσ_slice':
172
+ indices = key.indices(self._data.length)
173
+ start = indices[0]
174
+ stop = indices[1]
175
+ step = indices[2]
176
+ result = []
177
+ if step > 0:
178
+ for v'var i = start; i < stop; i += step':
179
+ result.push(self._data[i])
180
+ else:
181
+ for v'var i = start; i > stop; i += step':
182
+ result.push(self._data[i])
183
+ return ρσ_bytes(result)
184
+ n = key | 0
185
+ if n < 0:
186
+ n += self._data.length
187
+ if n < 0 or n >= self._data.length:
188
+ raise IndexError('index out of range')
189
+ return self._data[n]
190
+
191
+ def __contains__(self, item):
192
+ if v'item instanceof ρσ_bytes' or v'item instanceof ρσ_bytearray':
193
+ return ρσ_bytes_find(self._data, item._data, 0) >= 0
194
+ b = item | 0
195
+ for v'var i = 0; i < this._data.length; i++':
196
+ if self._data[i] is b:
197
+ return True
198
+ return False
199
+
200
+ def __add__(self, other):
201
+ if not (v'other instanceof ρσ_bytes' or v'other instanceof ρσ_bytearray'):
202
+ raise TypeError("can't concat bytes-like objects of different types")
203
+ return ρσ_bytes(self._data.concat(other._data))
204
+
205
+ def __mul__(self, n):
206
+ result = []
207
+ for v'var k = 0; k < n; k++':
208
+ for v'var j = 0; j < this._data.length; j++':
209
+ result.push(self._data[j])
210
+ return ρσ_bytes(result)
211
+
212
+ def __rmul__(self, n):
213
+ return self.__mul__(n)
214
+
215
+ def __eq__(self, other):
216
+ if not (v'other instanceof ρσ_bytes' or v'other instanceof ρσ_bytearray'):
217
+ return False
218
+ if self._data.length is not other._data.length:
219
+ return False
220
+ for v'var i = 0; i < this._data.length; i++':
221
+ if self._data[i] is not other._data[i]:
222
+ return False
223
+ return True
224
+
225
+ def __iter__(self):
226
+ return iter(self._data)
227
+
228
+ def __bool__(self):
229
+ return self._data.length > 0
230
+
231
+ def __repr__(self):
232
+ parts = ["b'"]
233
+ for v'var i = 0; i < this._data.length; i++':
234
+ b = self._data[i]
235
+ if b is 9:
236
+ parts.push('\\t')
237
+ elif b is 10:
238
+ parts.push('\\n')
239
+ elif b is 13:
240
+ parts.push('\\r')
241
+ elif b is 39:
242
+ parts.push("\\'")
243
+ elif b is 92:
244
+ parts.push('\\\\')
245
+ elif b >= 32 and b < 127:
246
+ parts.push(String.fromCharCode(b))
247
+ else:
248
+ h = b.toString(16)
249
+ parts.push('\\x' + ('0' if h.length < 2 else '') + h)
250
+ parts.push("'")
251
+ return parts.join('')
252
+
253
+ def __str__(self):
254
+ return self.__repr__()
255
+
256
+ def __hash__(self):
257
+ h = 5381
258
+ for v'var i = 0; i < this._data.length; i++':
259
+ h = ((h << 5) + h) ^ self._data[i]
260
+ h = h | 0
261
+ return h
262
+
263
+ def hex(self, sep, bytes_per_sep):
264
+ parts = []
265
+ for v'var i = 0; i < this._data.length; i++':
266
+ h = self._data[i].toString(16)
267
+ parts.push(('0' if h.length < 2 else '') + h)
268
+ if sep is not undefined and sep is not None and parts.length > 0:
269
+ n = 1 if (bytes_per_sep is undefined or bytes_per_sep is None) else (bytes_per_sep | 0)
270
+ if n < 0:
271
+ n = -n
272
+ grouped = []
273
+ i = parts.length
274
+ while i > 0:
275
+ grouped.unshift(parts.slice(max(0, i - n), i).join(''))
276
+ i -= n
277
+ return grouped.join(sep)
278
+ else:
279
+ grouped = []
280
+ for v'var i = 0; i < parts.length; i += n':
281
+ grouped.push(parts.slice(i, i + n).join(''))
282
+ return grouped.join(sep)
283
+ return parts.join('')
284
+
285
+ def decode(self, encoding, errors):
286
+ enc = (encoding or 'utf-8').toLowerCase().replace(/-|_/g, '')
287
+ if enc is 'utf8':
288
+ return ρσ_bytes_utf8_decode(self._data)
289
+ elif enc is 'latin1' or enc is 'iso88591' or enc is 'ascii':
290
+ return ρσ_bytes_latin1_decode(self._data)
291
+ else:
292
+ raise LookupError('unknown encoding: ' + (encoding or 'utf-8'))
293
+
294
+ @staticmethod
295
+ def fromhex(s):
296
+ s = s.replace(/ /g, '')
297
+ if s.length % 2 is not 0:
298
+ raise ValueError('non-hexadecimal number found in fromhex() arg')
299
+ data = []
300
+ for v'var i = 0; i < s.length; i += 2':
301
+ val = parseInt(s.slice(i, i + 2), 16)
302
+ if isNaN(val):
303
+ raise ValueError('non-hexadecimal number found in fromhex() arg at position ' + str(i))
304
+ data.push(val)
305
+ return ρσ_bytes(data)
306
+
307
+ def count(self, sub, start, end):
308
+ needle = [sub | 0] if jstype(sub) is 'number' else sub._data
309
+ s = 0 if start is undefined else (start | 0)
310
+ e = self._data.length if end is undefined else (end | 0)
311
+ n = 0
312
+ pos = s
313
+ while pos <= e - needle.length:
314
+ found = ρσ_bytes_find(self._data, needle, pos)
315
+ if found < 0 or found + needle.length > e:
316
+ break
317
+ n += 1
318
+ pos = found + max(1, needle.length)
319
+ return n
320
+
321
+ def find(self, sub, start, end):
322
+ needle = [sub | 0] if jstype(sub) is 'number' else sub._data
323
+ s = 0 if start is undefined else (start | 0)
324
+ e = self._data.length if end is undefined else (end | 0)
325
+ pos = ρσ_bytes_find(self._data, needle, s)
326
+ if pos >= 0 and pos + needle.length <= e:
327
+ return pos
328
+ return -1
329
+
330
+ def index(self, sub, start, end):
331
+ pos = self.find(sub, start, end)
332
+ if pos < 0:
333
+ raise ValueError('subsequence not found')
334
+ return pos
335
+
336
+ def rfind(self, sub, start, end):
337
+ needle = [sub | 0] if jstype(sub) is 'number' else sub._data
338
+ s = 0 if start is undefined else (start | 0)
339
+ e = self._data.length if end is undefined else (end | 0)
340
+ last = -1
341
+ pos = s
342
+ while pos <= e - needle.length:
343
+ found = ρσ_bytes_find(self._data, needle, pos)
344
+ if found < 0 or found + needle.length > e:
345
+ break
346
+ last = found
347
+ pos = found + max(1, needle.length)
348
+ return last
349
+
350
+ def rindex(self, sub, start, end):
351
+ pos = self.rfind(sub, start, end)
352
+ if pos < 0:
353
+ raise ValueError('subsequence not found')
354
+ return pos
355
+
356
+ def startswith(self, prefix, start, end):
357
+ s = 0 if start is undefined else (start | 0)
358
+ e = self._data.length if end is undefined else (end | 0)
359
+ pdata = [prefix | 0] if jstype(prefix) is 'number' else prefix._data
360
+ if pdata.length > e - s:
361
+ return False
362
+ for v'var i = 0; i < pdata.length; i++':
363
+ if self._data[s + i] is not pdata[i]:
364
+ return False
365
+ return True
366
+
367
+ def endswith(self, suffix, start, end):
368
+ s = 0 if start is undefined else (start | 0)
369
+ e = self._data.length if end is undefined else (end | 0)
370
+ sdata = [suffix | 0] if jstype(suffix) is 'number' else suffix._data
371
+ if sdata.length > e - s:
372
+ return False
373
+ offset = e - sdata.length
374
+ for v'var i = 0; i < sdata.length; i++':
375
+ if self._data[offset + i] is not sdata[i]:
376
+ return False
377
+ return True
378
+
379
+ def join(self, iterable):
380
+ parts = []
381
+ for item in iterable:
382
+ if not (v'item instanceof ρσ_bytes' or v'item instanceof ρσ_bytearray'):
383
+ raise TypeError('sequence item must be a bytes-like object')
384
+ parts.push(item._data)
385
+ result = []
386
+ for v'var i = 0; i < parts.length; i++':
387
+ if i > 0:
388
+ for v'var j = 0; j < this._data.length; j++':
389
+ result.push(self._data[j])
390
+ for v'var j = 0; j < parts[i].length; j++':
391
+ result.push(parts[i][j])
392
+ return ρσ_bytes(result)
393
+
394
+ def split(self, sep, maxsplit):
395
+ if maxsplit is undefined:
396
+ maxsplit = -1
397
+ if sep is None or sep is undefined or jstype(sep) is 'string':
398
+ # Split on whitespace
399
+ result = []
400
+ i = 0
401
+ n = self._data.length
402
+ while i < n:
403
+ while i < n and self._data[i] <= 32:
404
+ i += 1
405
+ if i >= n:
406
+ break
407
+ j = i
408
+ while j < n and self._data[j] > 32:
409
+ j += 1
410
+ result.push(ρσ_bytes(self._data.slice(i, j)))
411
+ i = j
412
+ if maxsplit >= 0 and result.length >= maxsplit:
413
+ while i < n and self._data[i] <= 32:
414
+ i += 1
415
+ if i < n:
416
+ result.push(ρσ_bytes(self._data.slice(i)))
417
+ break
418
+ return result
419
+ needle = sep._data
420
+ result = []
421
+ pos = 0
422
+ splits = 0
423
+ while True:
424
+ found = ρσ_bytes_find(self._data, needle, pos)
425
+ if found < 0 or (maxsplit >= 0 and splits >= maxsplit):
426
+ result.push(ρσ_bytes(self._data.slice(pos)))
427
+ break
428
+ result.push(ρσ_bytes(self._data.slice(pos, found)))
429
+ pos = found + needle.length
430
+ splits += 1
431
+ return result
432
+
433
+ def replace(self, old, replacement, count):
434
+ odata = old._data
435
+ ndata = replacement._data
436
+ result = []
437
+ pos = 0
438
+ n = 0
439
+ limit = count if (count is not undefined and count is not None) else -1
440
+ while pos <= self._data.length:
441
+ found = ρσ_bytes_find(self._data, odata, pos)
442
+ if found < 0 or (limit >= 0 and n >= limit):
443
+ for v'var i = pos; i < this._data.length; i++':
444
+ result.push(self._data[i])
445
+ break
446
+ for v'var i = pos; i < found; i++':
447
+ result.push(self._data[i])
448
+ for v'var i = 0; i < ndata.length; i++':
449
+ result.push(ndata[i])
450
+ pos = found + odata.length
451
+ n += 1
452
+ if odata.length is 0:
453
+ if pos < self._data.length:
454
+ result.push(self._data[pos])
455
+ pos += 1
456
+ else:
457
+ break
458
+ return ρσ_bytes(result)
459
+
460
+ def strip(self, chars):
461
+ return self.lstrip(chars).rstrip(chars)
462
+
463
+ def lstrip(self, chars):
464
+ is_ws = chars is None or chars is undefined
465
+ cdata = [] if is_ws else chars._data
466
+ i = 0
467
+ while i < self._data.length:
468
+ b = self._data[i]
469
+ if is_ws:
470
+ if b > 32:
471
+ break
472
+ else:
473
+ if cdata.indexOf(b) < 0:
474
+ break
475
+ i += 1
476
+ return ρσ_bytes(self._data.slice(i))
477
+
478
+ def rstrip(self, chars):
479
+ is_ws = chars is None or chars is undefined
480
+ cdata = [] if is_ws else chars._data
481
+ i = self._data.length - 1
482
+ while i >= 0:
483
+ b = self._data[i]
484
+ if is_ws:
485
+ if b > 32:
486
+ break
487
+ else:
488
+ if cdata.indexOf(b) < 0:
489
+ break
490
+ i -= 1
491
+ return ρσ_bytes(self._data.slice(0, i + 1))
492
+
493
+ def upper(self):
494
+ data = self._data.slice()
495
+ for v'var i = 0; i < data.length; i++':
496
+ b = data[i]
497
+ if b >= 97 and b <= 122:
498
+ data[i] = b - 32
499
+ return ρσ_bytes(data)
500
+
501
+ def lower(self):
502
+ data = self._data.slice()
503
+ for v'var i = 0; i < data.length; i++':
504
+ b = data[i]
505
+ if b >= 65 and b <= 90:
506
+ data[i] = b + 32
507
+ return ρσ_bytes(data)
508
+
509
+ def copy(self):
510
+ return ρσ_bytes(self._data.slice())
511
+
512
+ # .slice() and .filter() are called by the RapydScript compiler output for
513
+ # b[start:end] and b[start:end:step] subscript expressions respectively.
514
+ # They must return a new bytes object (not a plain array) so that sliced
515
+ # bytes values continue to behave as bytes.
516
+
517
+ def slice(self, start, end):
518
+ return ρσ_bytes(self._data.slice(start, end))
519
+
520
+ def filter(self, fn):
521
+ return ρσ_bytes(self._data.filter(fn))
522
+
523
+ ρσ_bytes.__name__ = 'bytes'
524
+
525
+ # ---------------------------------------------------------------------------
526
+ # bytearray — mutable version of bytes
527
+ # ---------------------------------------------------------------------------
528
+
529
+ class ρσ_bytearray(ρσ_bytes):
530
+ def __init__(self, source, encoding, errors):
531
+ self._data = ρσ_bytes_from_source.apply(None, arguments)
532
+ ρσ_bytes_sync(self)
533
+
534
+ def __setitem__(self, key, val):
535
+ if v'key instanceof ρσ_slice':
536
+ indices = key.indices(self._data.length)
537
+ start = indices[0]
538
+ stop = indices[1]
539
+ step = indices[2]
540
+ if v'val instanceof ρσ_bytes' or v'val instanceof ρσ_bytearray':
541
+ src = val._data
542
+ else:
543
+ src = ρσ_bytes_from_source(val)
544
+ if step is 1:
545
+ self._data.splice.apply(self._data, [start, stop - start].concat(src))
546
+ else:
547
+ positions = []
548
+ if step > 0:
549
+ for v'var i = start; i < stop; i += step':
550
+ positions.push(i)
551
+ else:
552
+ for v'var i = start; i > stop; i += step':
553
+ positions.push(i)
554
+ if src.length is not positions.length:
555
+ raise ValueError('attempt to assign bytes of size ' + str(src.length) + ' to extended slice of size ' + str(positions.length))
556
+ for v'var i = 0; i < positions.length; i++':
557
+ self._data[positions[i]] = src[i]
558
+ ρσ_bytes_sync(self)
559
+ else:
560
+ n = key | 0
561
+ if n < 0:
562
+ n += self._data.length
563
+ if n < 0 or n >= self._data.length:
564
+ raise IndexError('index out of range')
565
+ b = val | 0
566
+ if b < 0 or b > 255:
567
+ raise ValueError('byte must be in range(0, 256)')
568
+ self._data[n] = b
569
+ self[n] = b
570
+
571
+ def __add__(self, other):
572
+ if not (v'other instanceof ρσ_bytes' or v'other instanceof ρσ_bytearray'):
573
+ raise TypeError("can't concat bytes-like objects of different types")
574
+ return ρσ_bytearray(self._data.concat(other._data))
575
+
576
+ def __iadd__(self, other):
577
+ if not (v'other instanceof ρσ_bytes' or v'other instanceof ρσ_bytearray'):
578
+ raise TypeError("can't concat bytes-like objects of different types")
579
+ for v'var i = 0; i < other._data.length; i++':
580
+ self._data.push(other._data[i])
581
+ ρσ_bytes_sync(self)
582
+ return self
583
+
584
+ def __mul__(self, n):
585
+ result = []
586
+ for v'var k = 0; k < n; k++':
587
+ for v'var j = 0; j < this._data.length; j++':
588
+ result.push(self._data[j])
589
+ return ρσ_bytearray(result)
590
+
591
+ def __repr__(self):
592
+ b = ρσ_bytes.prototype.__repr__.call(self)
593
+ return 'bytearray(' + b + ')'
594
+
595
+ def append(self, item):
596
+ b = item | 0
597
+ if b < 0 or b > 255:
598
+ raise ValueError('byte must be in range(0, 256)')
599
+ idx = self._data.length
600
+ self._data.push(b)
601
+ self[idx] = b
602
+ self.length = self._data.length
603
+
604
+ def extend(self, iterable):
605
+ if v'iterable instanceof ρσ_bytes' or v'iterable instanceof ρσ_bytearray':
606
+ for v'var i = 0; i < iterable._data.length; i++':
607
+ self._data.push(iterable._data[i])
608
+ else:
609
+ for x in iterable:
610
+ b = x | 0
611
+ if b < 0 or b > 255:
612
+ raise ValueError('byte must be in range(0, 256)')
613
+ self._data.push(b)
614
+ ρσ_bytes_sync(self)
615
+
616
+ def insert(self, idx, item):
617
+ n = idx | 0
618
+ if n < 0:
619
+ n = max(0, self._data.length + n)
620
+ b = item | 0
621
+ if b < 0 or b > 255:
622
+ raise ValueError('byte must be in range(0, 256)')
623
+ self._data.splice(n, 0, b)
624
+ ρσ_bytes_sync(self)
625
+
626
+ def pop(self, idx):
627
+ n = self._data.length - 1 if idx is undefined else (idx | 0)
628
+ if n < 0:
629
+ n += self._data.length
630
+ if n < 0 or n >= self._data.length:
631
+ raise IndexError('pop index out of range')
632
+ val = self._data.splice(n, 1)[0]
633
+ ρσ_bytes_sync(self)
634
+ return val
635
+
636
+ def remove(self, item):
637
+ b = item | 0
638
+ for v'var i = 0; i < this._data.length; i++':
639
+ if self._data[i] is b:
640
+ self._data.splice(i, 1)
641
+ ρσ_bytes_sync(self)
642
+ return
643
+ raise ValueError(str(item) + ' is not in bytearray')
644
+
645
+ def reverse(self):
646
+ self._data.reverse()
647
+ ρσ_bytes_sync(self)
648
+
649
+ def clear(self):
650
+ self._data.length = 0
651
+ ρσ_bytes_sync(self)
652
+
653
+ def copy(self):
654
+ return ρσ_bytearray(self._data.slice())
655
+
656
+ def slice(self, start, end):
657
+ return ρσ_bytearray(self._data.slice(start, end))
658
+
659
+ def filter(self, fn):
660
+ return ρσ_bytearray(self._data.filter(fn))
661
+
662
+ ρσ_bytearray.__name__ = 'bytearray'
663
+
664
+ v'var bytes = ρσ_bytes, bytearray = ρσ_bytearray'