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
package/test/baselib.pyj CHANGED
@@ -99,6 +99,20 @@ assrt.deepEqual(list(map(def(a):return a*2;, iter([1, 2]))), [2, 4])
99
99
  assrt.deepEqual(list(filter(def(a):return a > 1;, [1, 2])), [2])
100
100
  assrt.deepEqual(list(filter(def(a):return a > 1;, iter([1, 2]))), [2])
101
101
  assrt.deepEqual(list(zip([1,2], [3,4])), [[1,3], [2, 4]])
102
+ assrt.deepEqual(list(zip([1,2], [3,4], strict=True)), [[1,3], [2, 4]])
103
+ assrt.deepEqual(list(zip(strict=True)), [])
104
+ _zip_err = False
105
+ try:
106
+ list(zip([1,2], [3], strict=True))
107
+ except:
108
+ _zip_err = True
109
+ assrt.ok(_zip_err)
110
+ _zip_err2 = False
111
+ try:
112
+ list(zip([1], [3,4], strict=True))
113
+ except:
114
+ _zip_err2 = True
115
+ assrt.ok(_zip_err2)
102
116
 
103
117
  # lists
104
118
  a = [1, 2]
@@ -317,3 +331,80 @@ assrt.equal(all(iter([1, 2, 3])), True)
317
331
  assrt.equal(all(iter([1, 0, 3])), False)
318
332
  assrt.equal(all(range(1, 4)), True)
319
333
  assrt.equal(all(range(0, 3)), False)
334
+
335
+ # complex() builtin and j-literal syntax
336
+ c1 = complex(3, 4)
337
+ assrt.equal(c1.real, 3)
338
+ assrt.equal(c1.imag, 4)
339
+
340
+ # j literal syntax
341
+ c2 = 4j
342
+ assrt.equal(c2.real, 0)
343
+ assrt.equal(c2.imag, 4)
344
+
345
+ # 3+4j literal — + goes through ρσ_list_add which dispatches __add__
346
+ c3 = 3+4j
347
+ assrt.equal(c3.real, 3)
348
+ assrt.equal(c3.imag, 4)
349
+
350
+ # abs() dispatches to __abs__
351
+ assrt.equal(abs(complex(3, 4)), 5.0)
352
+ assrt.equal(abs(complex(-5, 0)), 5)
353
+
354
+ # arithmetic via dunder methods (no overload_operators needed)
355
+ assrt.ok(complex(1, 2).__add__(complex(3, 4)) == complex(4, 6))
356
+ assrt.ok(complex(5, 6).__sub__(complex(3, 4)) == complex(2, 2))
357
+ assrt.ok(complex(1, 2).__mul__(complex(3, 4)) == complex(-5, 10))
358
+ assrt.ok(complex(2, 0).__truediv__(complex(4, 0)) == complex(0.5, 0))
359
+
360
+ # mixed complex + number
361
+ assrt.ok(complex(3, 4) + 1 == complex(4, 4)) # ρσ_list_add → __add__
362
+ assrt.ok(complex(3, 4).__radd__(1) == complex(4, 4))
363
+ assrt.ok(complex(3, 4).__sub__(1) == complex(2, 4))
364
+ assrt.ok(complex(3, 4).__rmul__(2) == complex(6, 8))
365
+ assrt.ok(complex(6, 8).__truediv__(2) == complex(3, 4))
366
+
367
+ # 1 + complex — ρσ_list_add dispatches __radd__ when left has no __add__
368
+ assrt.ok(1 + complex(3, 4) == complex(4, 4))
369
+
370
+ # unary via dunder
371
+ assrt.ok(complex(3, 4).__neg__() == complex(-3, -4))
372
+ assrt.ok(complex(3, 4).__pos__() == complex(3, 4))
373
+
374
+ # conjugate
375
+ assrt.ok(complex(3, 4).conjugate() == complex(3, -4))
376
+
377
+ # zero-argument form
378
+ assrt.ok(complex() == complex(0, 0))
379
+
380
+ # single-argument number
381
+ assrt.ok(complex(5) == complex(5, 0))
382
+
383
+ # single-argument string
384
+ assrt.ok(complex('3+4j') == complex(3, 4))
385
+ assrt.ok(complex('3-4j') == complex(3, -4))
386
+ assrt.ok(complex('4j') == complex(0, 4))
387
+ assrt.ok(complex('3') == complex(3, 0))
388
+ assrt.ok(complex('j') == complex(0, 1))
389
+ assrt.ok(complex('-j') == complex(0, -1))
390
+
391
+ # isinstance
392
+ assrt.ok(isinstance(complex(1, 2), complex))
393
+ assrt.ok(not isinstance(42, complex))
394
+
395
+ # bool — __bool__ dispatch works, and truthiness is correct in conditions
396
+ assrt.ok(complex(0, 0).__bool__() is False)
397
+ assrt.ok(complex(1, 0).__bool__() is True)
398
+ assrt.ok(complex(0, 1).__bool__() is True)
399
+
400
+ # repr / str
401
+ assrt.equal(repr(complex(0, 0)), '0j')
402
+ assrt.equal(repr(complex(1, 0)), '(1+0j)')
403
+ assrt.equal(repr(complex(0, 1)), '1j')
404
+ assrt.equal(repr(complex(3, 4)), '(3+4j)')
405
+ assrt.equal(repr(complex(3, -4)), '(3-4j)')
406
+ assrt.equal(str(complex(3, 4)), '(3+4j)')
407
+
408
+ # abs() still works on numbers
409
+ assrt.equal(abs(-5), 5)
410
+ assrt.equal(abs(3.0), 3.0)
package/test/bytes.pyj ADDED
@@ -0,0 +1,467 @@
1
+ # vim:fileencoding=utf-8
2
+ # globals: assrt
3
+ from __python__ import overload_operators, truthiness
4
+
5
+ ae = assrt.equal
6
+ ade = assrt.deepEqual
7
+ ok = assrt.ok
8
+
9
+ # ---------------------------------------------------------------------------
10
+ # Construction
11
+ # ---------------------------------------------------------------------------
12
+
13
+ # Empty bytes
14
+ b = bytes()
15
+ ae(len(b), 0)
16
+ ok(isinstance(b, bytes))
17
+
18
+ # From integer — n zero bytes
19
+ b = bytes(4)
20
+ ae(len(b), 4)
21
+ ae(b[0], 0)
22
+ ae(b[3], 0)
23
+
24
+ # From list of ints
25
+ b = bytes([72, 101, 108, 108, 111])
26
+ ae(len(b), 5)
27
+ ae(b[0], 72)
28
+ ae(b[4], 111)
29
+
30
+ # From string with encoding
31
+ b = bytes('Hello', 'utf-8')
32
+ ae(len(b), 5)
33
+ ae(b[0], 72) # H
34
+ ae(b[1], 101) # e
35
+
36
+ # From another bytes object (copy)
37
+ b2 = bytes(b)
38
+ ok(b2 == b)
39
+ ok(b2 is not b)
40
+
41
+ # ---------------------------------------------------------------------------
42
+ # bytearray construction
43
+ # ---------------------------------------------------------------------------
44
+
45
+ ba = bytearray()
46
+ ae(len(ba), 0)
47
+ ok(isinstance(ba, bytearray))
48
+
49
+ ba = bytearray(3)
50
+ ae(len(ba), 3)
51
+ ae(ba[0], 0)
52
+
53
+ ba = bytearray([1, 2, 3])
54
+ ae(ba[0], 1)
55
+ ae(ba[2], 3)
56
+
57
+ ba = bytearray('Hi', 'utf-8')
58
+ ae(ba[0], 72) # H
59
+ ae(ba[1], 105) # i
60
+
61
+ # From bytes (copy)
62
+ src = bytes([10, 20, 30])
63
+ ba = bytearray(src)
64
+ ok(ba == src)
65
+ ok(ba is not src)
66
+
67
+ # ---------------------------------------------------------------------------
68
+ # isinstance checks
69
+ # ---------------------------------------------------------------------------
70
+
71
+ ok(isinstance(bytes([1, 2]), bytes))
72
+ ok(isinstance(bytearray([1, 2]), bytearray))
73
+ ok(isinstance(bytearray([1, 2]), bytes)) # bytearray is subclass of bytes
74
+
75
+ # ---------------------------------------------------------------------------
76
+ # Indexing and slicing
77
+ # ---------------------------------------------------------------------------
78
+
79
+ b = bytes([10, 20, 30, 40, 50])
80
+
81
+ # Integer index
82
+ ae(b[0], 10)
83
+ ae(b[-1], 50)
84
+ ae(b[2], 30)
85
+
86
+ # Slice returns bytes
87
+ s = b[1:4]
88
+ ok(isinstance(s, bytes))
89
+ ae(len(s), 3)
90
+ ae(s[0], 20)
91
+ ae(s[2], 40)
92
+
93
+ # Slice with step
94
+ s = b[::2]
95
+ ae(len(s), 3)
96
+ ae(s[0], 10)
97
+ ae(s[1], 30)
98
+ ae(s[2], 50)
99
+
100
+ # Negative slice
101
+ s = b[-2:]
102
+ ae(len(s), 2)
103
+ ae(s[0], 40)
104
+ ae(s[1], 50)
105
+
106
+ # ---------------------------------------------------------------------------
107
+ # bytearray item assignment
108
+ # ---------------------------------------------------------------------------
109
+
110
+ ba = bytearray([1, 2, 3, 4, 5])
111
+ ba[0] = 99
112
+ ae(ba[0], 99)
113
+
114
+ ba[-1] = 88
115
+ ae(ba[4], 88)
116
+
117
+ # Slice assignment via __setitem__
118
+ ba.__setitem__(slice(1, 3), bytes([20, 30]))
119
+ ae(ba[1], 20)
120
+ ae(ba[2], 30)
121
+
122
+ # ---------------------------------------------------------------------------
123
+ # Equality
124
+ # ---------------------------------------------------------------------------
125
+
126
+ ok(bytes([1, 2, 3]) == bytes([1, 2, 3]))
127
+ ok(not (bytes([1, 2, 3]) == bytes([1, 2, 4])))
128
+ ok(bytes([1, 2]) == bytearray([1, 2]))
129
+ ok(bytearray([1, 2]) == bytes([1, 2]))
130
+
131
+ # ---------------------------------------------------------------------------
132
+ # Concatenation and repetition
133
+ # ---------------------------------------------------------------------------
134
+
135
+ b1 = bytes([1, 2])
136
+ b2 = bytes([3, 4])
137
+ b3 = b1 + b2
138
+ ae(len(b3), 4)
139
+ ae(b3[0], 1)
140
+ ae(b3[3], 4)
141
+
142
+ b4 = bytes([7]) * 3
143
+ ae(len(b4), 3)
144
+ ae(b4[0], 7)
145
+ ae(b4[2], 7)
146
+
147
+ ba = bytearray([1, 2])
148
+ ba += bytearray([3, 4])
149
+ ae(len(ba), 4)
150
+ ae(ba[2], 3)
151
+
152
+ # ---------------------------------------------------------------------------
153
+ # Containment
154
+ # ---------------------------------------------------------------------------
155
+
156
+ b = bytes([10, 20, 30, 40])
157
+ ok(20 in b)
158
+ ok(not (99 in b))
159
+ ok(bytes([20, 30]) in b)
160
+ ok(not (bytes([20, 40]) in b))
161
+
162
+ # ---------------------------------------------------------------------------
163
+ # Iteration
164
+ # ---------------------------------------------------------------------------
165
+
166
+ b = bytes([5, 10, 15])
167
+ vals = [x for x in b]
168
+ ade(vals, [5, 10, 15])
169
+
170
+ total = 0
171
+ for byte in bytes([1, 2, 3, 4]):
172
+ total += byte
173
+ ae(total, 10)
174
+
175
+ # ---------------------------------------------------------------------------
176
+ # hex() and fromhex()
177
+ # ---------------------------------------------------------------------------
178
+
179
+ b = bytes([0, 15, 255])
180
+ ae(b.hex(), '000fff')
181
+
182
+ ae(bytes([72, 101, 108, 108, 111]).hex(), '48656c6c6f')
183
+
184
+ b2 = bytes.fromhex('48656c6c6f')
185
+ ok(b2 == bytes([72, 101, 108, 108, 111]))
186
+
187
+ # hex() with separator
188
+ b = bytes([1, 2, 3])
189
+ ae(b.hex(':', 1), '01:02:03')
190
+
191
+ # ---------------------------------------------------------------------------
192
+ # decode()
193
+ # ---------------------------------------------------------------------------
194
+
195
+ b = bytes([72, 101, 108, 108, 111])
196
+ ae(b.decode('utf-8'), 'Hello')
197
+
198
+ b = bytes('café', 'utf-8')
199
+ ae(b.decode('utf-8'), 'café')
200
+
201
+ b = bytes([65, 66, 67])
202
+ ae(b.decode('ascii'), 'ABC')
203
+
204
+ # ---------------------------------------------------------------------------
205
+ # count(), find(), index(), rfind(), rindex()
206
+ # ---------------------------------------------------------------------------
207
+
208
+ b = bytes([1, 2, 1, 2, 1])
209
+ ae(b.count(1), 3)
210
+ ae(b.count(bytes([1, 2])), 2)
211
+
212
+ ae(b.find(1), 0)
213
+ ae(b.find(2), 1)
214
+ ae(b.find(bytes([1, 2])), 0)
215
+ ae(b.find(99), -1)
216
+
217
+ ae(b.index(2), 1)
218
+
219
+ ae(b.rfind(1), 4)
220
+ ae(b.rindex(2), 3)
221
+
222
+ # ---------------------------------------------------------------------------
223
+ # startswith() / endswith()
224
+ # ---------------------------------------------------------------------------
225
+
226
+ b = bytes([1, 2, 3, 4, 5])
227
+ ok(b.startswith(bytes([1, 2])))
228
+ ok(not b.startswith(bytes([2, 3])))
229
+ ok(b.endswith(bytes([4, 5])))
230
+ ok(not b.endswith(bytes([3, 4])))
231
+
232
+ # ---------------------------------------------------------------------------
233
+ # join()
234
+ # ---------------------------------------------------------------------------
235
+
236
+ sep = bytes([0])
237
+ parts = [bytes([1]), bytes([2]), bytes([3])]
238
+ result = sep.join(parts)
239
+ ade(list(result), [1, 0, 2, 0, 3])
240
+
241
+ # Empty separator
242
+ result = bytes().join([bytes([1, 2]), bytes([3, 4])])
243
+ ade(list(result), [1, 2, 3, 4])
244
+
245
+ # ---------------------------------------------------------------------------
246
+ # split()
247
+ # ---------------------------------------------------------------------------
248
+
249
+ b = bytes([1, 0, 2, 0, 3])
250
+ parts = b.split(bytes([0]))
251
+ ae(len(parts), 3)
252
+ ok(parts[0] == bytes([1]))
253
+ ok(parts[1] == bytes([2]))
254
+ ok(parts[2] == bytes([3]))
255
+
256
+ # Split with maxsplit
257
+ parts = b.split(bytes([0]), 1)
258
+ ae(len(parts), 2)
259
+ ok(parts[0] == bytes([1]))
260
+ ok(parts[1] == bytes([2, 0, 3]))
261
+
262
+ # Whitespace split
263
+ b = bytes([32, 65, 32, 66, 32])
264
+ parts = b.split()
265
+ ae(len(parts), 2)
266
+ ok(parts[0] == bytes([65]))
267
+ ok(parts[1] == bytes([66]))
268
+
269
+ # ---------------------------------------------------------------------------
270
+ # replace()
271
+ # ---------------------------------------------------------------------------
272
+
273
+ b = bytes([1, 2, 3, 1, 2])
274
+ r = b.replace(bytes([1, 2]), bytes([9]))
275
+ ade(list(r), [9, 3, 9])
276
+
277
+ r = b.replace(bytes([1, 2]), bytes([9]), 1)
278
+ ade(list(r), [9, 3, 1, 2])
279
+
280
+ # ---------------------------------------------------------------------------
281
+ # strip() / lstrip() / rstrip()
282
+ # ---------------------------------------------------------------------------
283
+
284
+ b = bytes([32, 32, 65, 66, 32])
285
+ ok(b.strip() == bytes([65, 66]))
286
+ ok(b.lstrip() == bytes([65, 66, 32]))
287
+ ok(b.rstrip() == bytes([32, 32, 65, 66]))
288
+
289
+ b = bytes([1, 2, 65, 66, 2, 1])
290
+ ok(b.strip(bytes([1, 2])) == bytes([65, 66]))
291
+
292
+ # ---------------------------------------------------------------------------
293
+ # upper() / lower()
294
+ # ---------------------------------------------------------------------------
295
+
296
+ b = bytes([104, 101, 108, 108, 111]) # hello
297
+ ok(b.upper() == bytes([72, 69, 76, 76, 79])) # HELLO
298
+
299
+ b = bytes([72, 69, 76, 76, 79]) # HELLO
300
+ ok(b.lower() == bytes([104, 101, 108, 108, 111]))
301
+
302
+ # ---------------------------------------------------------------------------
303
+ # bytearray mutation methods
304
+ # ---------------------------------------------------------------------------
305
+
306
+ ba = bytearray([1, 2, 3])
307
+
308
+ ba.append(4)
309
+ ade(list(ba), [1, 2, 3, 4])
310
+
311
+ ba.extend([5, 6])
312
+ ade(list(ba), [1, 2, 3, 4, 5, 6])
313
+
314
+ ba.insert(0, 0)
315
+ ae(ba[0], 0)
316
+ ae(len(ba), 7)
317
+
318
+ popped = ba.pop()
319
+ ae(popped, 6)
320
+ ae(len(ba), 6)
321
+
322
+ popped = ba.pop(0)
323
+ ae(popped, 0)
324
+ ae(ba[0], 1)
325
+
326
+ ba.remove(3)
327
+ ok(not (3 in ba))
328
+
329
+ ba2 = bytearray([10, 20, 30])
330
+ ba2.reverse()
331
+ ade(list(ba2), [30, 20, 10])
332
+
333
+ ba3 = bytearray([1, 2, 3])
334
+ ba3.clear()
335
+ ae(len(ba3), 0)
336
+
337
+ # ---------------------------------------------------------------------------
338
+ # copy()
339
+ # ---------------------------------------------------------------------------
340
+
341
+ b = bytes([1, 2, 3])
342
+ b2 = b.copy()
343
+ ok(b == b2)
344
+ ok(b is not b2)
345
+
346
+ ba = bytearray([1, 2, 3])
347
+ ba2 = ba.copy()
348
+ ok(ba == ba2)
349
+ ok(ba is not ba2)
350
+ ok(isinstance(ba2, bytearray))
351
+
352
+ # ---------------------------------------------------------------------------
353
+ # repr() / str()
354
+ # ---------------------------------------------------------------------------
355
+
356
+ b = bytes([72, 101, 108, 108, 111])
357
+ ae(repr(b), "b'Hello'")
358
+ ae(str(b), "b'Hello'")
359
+
360
+ b = bytes([0, 1, 255])
361
+ ae(repr(b), "b'\\x00\\x01\\xff'")
362
+
363
+ b = bytes([10, 13, 9, 39, 92])
364
+ ae(repr(b), "b'\\n\\r\\t\\'\\\\'")
365
+
366
+ ba = bytearray([72, 105])
367
+ ok(repr(ba).startsWith('bytearray('))
368
+
369
+ # ---------------------------------------------------------------------------
370
+ # bool / truthiness
371
+ # ---------------------------------------------------------------------------
372
+
373
+ ok(not bytes())
374
+ ok(bytes([0]))
375
+ ok(not bytearray())
376
+ ok(bytearray([0]))
377
+
378
+ # ---------------------------------------------------------------------------
379
+ # hash()
380
+ # ---------------------------------------------------------------------------
381
+
382
+ b1 = bytes([1, 2, 3])
383
+ b2 = bytes([1, 2, 3])
384
+ ae(hash(b1), hash(b2))
385
+
386
+ # ---------------------------------------------------------------------------
387
+ # Uint8Array interop
388
+ # ---------------------------------------------------------------------------
389
+
390
+ ua = v'new Uint8Array([10, 20, 30])'
391
+ b = bytes(ua)
392
+ ae(len(b), 3)
393
+ ae(b[0], 10)
394
+ ae(b[2], 30)
395
+
396
+ # ---------------------------------------------------------------------------
397
+ # b'...' bytes literal syntax
398
+ # ---------------------------------------------------------------------------
399
+
400
+ # Basic ASCII literal
401
+ b = b'Hello'
402
+ ok(isinstance(b, bytes))
403
+ ae(len(b), 5)
404
+ ae(b[0], 72) # H
405
+ ae(b[1], 101) # e
406
+ ae(b[4], 111) # o
407
+ ok(b == bytes([72, 101, 108, 108, 111]))
408
+
409
+ # Uppercase B prefix
410
+ b = B'ABC'
411
+ ok(isinstance(b, bytes))
412
+ ae(len(b), 3)
413
+ ae(b[0], 65) # A
414
+
415
+ # Empty bytes literal
416
+ b = b''
417
+ ae(len(b), 0)
418
+ ok(isinstance(b, bytes))
419
+
420
+ # Hex escape sequences
421
+ b = b'\x48\x65\x6c\x6c\x6f' # Hello
422
+ ae(len(b), 5)
423
+ ae(b[0], 72)
424
+ ok(b == bytes([72, 101, 108, 108, 111]))
425
+
426
+ # Control character escapes
427
+ b = b'\n\t\r'
428
+ ae(len(b), 3)
429
+ ae(b[0], 10) # \n
430
+ ae(b[1], 9) # \t
431
+ ae(b[2], 13) # \r
432
+
433
+ # Null byte and max Latin-1 byte
434
+ b = b'\x00\xff'
435
+ ae(len(b), 2)
436
+ ae(b[0], 0)
437
+ ae(b[1], 255)
438
+
439
+ # Adjacent bytes literal concatenation
440
+ b = b'foo' b'bar'
441
+ ae(len(b), 6)
442
+ ok(b == bytes([102, 111, 111, 98, 97, 114])) # foobar
443
+
444
+ # Raw bytes literal - backslash sequences not interpreted
445
+ b = rb'\n\t'
446
+ ae(len(b), 4)
447
+ ae(b[0], 92) # backslash
448
+ ae(b[1], 110) # n
449
+ ae(b[2], 92) # backslash
450
+ ae(b[3], 116) # t
451
+
452
+ # Double-quoted bytes literal
453
+ b = b"World"
454
+ ae(len(b), 5)
455
+ ae(b[0], 87) # W
456
+
457
+ # bytes literal behaves like bytes constructed from equivalent list
458
+ b1 = b'Hello'
459
+ b2 = bytes([72, 101, 108, 108, 111])
460
+ ok(b1 == b2)
461
+ ok(b1.decode('utf-8') is 'Hello')
462
+
463
+ # Operations on bytes from literal
464
+ b = b'hello'
465
+ ok(b.upper() == bytes([72, 69, 76, 76, 79]))
466
+ ae(len(b + b'!'), 6)
467
+ ok(b'\x00\x01' + b'\x02' == bytes([0, 1, 2]))
package/test/classes.pyj CHANGED
@@ -69,6 +69,7 @@ assrt.equal(bound(), angela.how_long())
69
69
  # function methods
70
70
  assrt.deepEqual(sorted(dir(angela)), [
71
71
  'HAIRS',
72
+ '__format__',
72
73
  "__init__",
73
74
  '__repr__',
74
75
  '__str__',