rapydscript-ns 0.8.4 → 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.
- package/.agignore +1 -1
- package/.github/workflows/ci.yml +38 -38
- package/=template.pyj +5 -5
- package/CHANGELOG.md +18 -0
- package/HACKING.md +103 -103
- package/LICENSE +24 -24
- package/README.md +715 -169
- package/TODO.md +9 -2
- package/add-toc-to-readme +2 -2
- package/bin/export +75 -75
- package/bin/rapydscript +70 -70
- package/bin/web-repl-export +102 -102
- package/build +2 -2
- package/language-service/index.js +36 -27
- package/package.json +1 -1
- package/publish.py +37 -37
- package/release/baselib-plain-pretty.js +2358 -168
- package/release/baselib-plain-ugly.js +73 -3
- package/release/compiler.js +6282 -3092
- package/release/signatures.json +31 -30
- package/session.vim +4 -4
- package/setup.cfg +2 -2
- package/src/ast.pyj +1 -0
- package/src/baselib-builtins.pyj +340 -2
- package/src/baselib-bytes.pyj +664 -0
- package/src/baselib-errors.pyj +1 -1
- package/src/baselib-internal.pyj +267 -60
- package/src/baselib-itertools.pyj +110 -97
- package/src/baselib-str.pyj +22 -4
- package/src/compiler.pyj +36 -36
- package/src/errors.pyj +30 -30
- package/src/lib/abc.pyj +317 -0
- package/src/lib/aes.pyj +646 -646
- package/src/lib/copy.pyj +120 -120
- package/src/lib/dataclasses.pyj +532 -0
- package/src/lib/elementmaker.pyj +83 -83
- package/src/lib/encodings.pyj +126 -126
- package/src/lib/enum.pyj +125 -0
- 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/pythonize.pyj +20 -20
- package/src/lib/random.pyj +118 -118
- package/src/lib/re.pyj +504 -470
- package/src/lib/react.pyj +74 -74
- package/src/lib/traceback.pyj +63 -63
- package/src/lib/typing.pyj +577 -0
- package/src/lib/uuid.pyj +77 -77
- package/src/monaco-language-service/builtins.js +14 -4
- package/src/monaco-language-service/diagnostics.js +19 -20
- package/src/monaco-language-service/dts.js +550 -550
- package/src/output/classes.pyj +62 -26
- package/src/output/comments.pyj +45 -45
- package/src/output/exceptions.pyj +201 -201
- package/src/output/functions.pyj +78 -5
- package/src/output/jsx.pyj +164 -164
- package/src/output/loops.pyj +5 -2
- package/src/output/operators.pyj +100 -34
- package/src/output/treeshake.pyj +182 -182
- package/src/output/utils.pyj +72 -72
- package/src/parse.pyj +80 -16
- package/src/string_interpolation.pyj +72 -72
- package/src/tokenizer.pyj +9 -4
- 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/abc.pyj +291 -0
- package/test/aes_vectors.pyj +421 -421
- package/test/annotations.pyj +80 -80
- package/test/arithmetic_nostrict.pyj +88 -0
- package/test/arithmetic_types.pyj +169 -0
- package/test/baselib.pyj +91 -0
- package/test/bytes.pyj +467 -0
- package/test/classes.pyj +1 -0
- package/test/comparison_ops.pyj +173 -0
- package/test/dataclasses.pyj +253 -0
- package/test/decorators.pyj +77 -77
- package/test/docstrings.pyj +39 -39
- package/test/elementmaker_test.pyj +45 -45
- package/test/enum.pyj +134 -0
- package/test/eval_exec.pyj +56 -0
- package/test/format.pyj +148 -0
- package/test/functions.pyj +151 -151
- package/test/generators.pyj +41 -41
- package/test/generic.pyj +370 -370
- package/test/imports.pyj +72 -72
- 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/object.pyj +64 -0
- package/test/omit_function_metadata.pyj +20 -20
- package/test/python_compat.pyj +17 -15
- package/test/python_features.pyj +70 -15
- package/test/regexp.pyj +83 -55
- package/test/repl.pyj +121 -121
- package/test/scoped_flags.pyj +76 -76
- package/test/tuples.pyj +96 -0
- package/test/typing.pyj +469 -0
- package/test/unit/index.js +116 -7
- package/test/unit/language-service-dts.js +543 -543
- package/test/unit/language-service-hover.js +455 -455
- package/test/unit/language-service.js +84 -0
- package/test/unit/web-repl.js +804 -1
- package/test/vars_locals_globals.pyj +94 -0
- package/tools/cli.js +558 -547
- package/tools/compile.js +224 -219
- package/tools/completer.js +131 -131
- package/tools/embedded_compiler.js +262 -251
- package/tools/gettext.js +185 -185
- package/tools/ini.js +65 -65
- package/tools/lint.js +16 -19
- 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/main.js +252 -252
- package/web-repl/prism.css +139 -139
- package/web-repl/prism.js +113 -113
- package/web-repl/rapydscript.js +224 -224
- package/web-repl/sha1.js +25 -25
- package/PYTHON_DIFFERENCES_REPORT.md +0 -291
- package/PYTHON_FEATURE_COVERAGE.md +0 -200
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
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
from __python__ import overload_operators
|
|
2
|
+
|
|
3
|
+
# ── helpers ──────────────────────────────────────────────────────────────────
|
|
4
|
+
|
|
5
|
+
def _raises(fn, exc_type):
|
|
6
|
+
"""Return True if fn() raises exc_type, False otherwise."""
|
|
7
|
+
try:
|
|
8
|
+
fn()
|
|
9
|
+
except exc_type:
|
|
10
|
+
return True
|
|
11
|
+
return False
|
|
12
|
+
|
|
13
|
+
# ── 1. Numeric comparisons (should still work correctly) ─────────────────────
|
|
14
|
+
|
|
15
|
+
assert 1 < 2
|
|
16
|
+
assert not (2 < 1)
|
|
17
|
+
assert 2 > 1
|
|
18
|
+
assert not (1 > 2)
|
|
19
|
+
assert 1 <= 1
|
|
20
|
+
assert 2 <= 3
|
|
21
|
+
assert not (3 <= 2)
|
|
22
|
+
assert 3 >= 3
|
|
23
|
+
assert 3 >= 2
|
|
24
|
+
assert not (2 >= 3)
|
|
25
|
+
|
|
26
|
+
# ── 2. String comparisons ────────────────────────────────────────────────────
|
|
27
|
+
|
|
28
|
+
assert 'abc' < 'abd'
|
|
29
|
+
assert 'abc' <= 'abc'
|
|
30
|
+
assert 'z' > 'a'
|
|
31
|
+
assert 'abc' >= 'abc'
|
|
32
|
+
assert not ('b' < 'a')
|
|
33
|
+
|
|
34
|
+
# ── 3. List lexicographic ordering ───────────────────────────────────────────
|
|
35
|
+
|
|
36
|
+
# First differing element determines order
|
|
37
|
+
assert [1, 2] < [1, 3]
|
|
38
|
+
assert not ([1, 3] < [1, 2])
|
|
39
|
+
|
|
40
|
+
# Prefix rule: shorter list with equal prefix is smaller
|
|
41
|
+
assert [1, 2] < [1, 2, 0]
|
|
42
|
+
assert not ([1, 2, 0] < [1, 2])
|
|
43
|
+
|
|
44
|
+
# First element dominates
|
|
45
|
+
assert [2] > [1, 99]
|
|
46
|
+
assert not ([1, 99] > [2])
|
|
47
|
+
|
|
48
|
+
# Equal lists
|
|
49
|
+
assert [1, 2] <= [1, 2]
|
|
50
|
+
assert [1, 2] >= [1, 2]
|
|
51
|
+
assert not ([1, 2] < [1, 2])
|
|
52
|
+
assert not ([1, 2] > [1, 2])
|
|
53
|
+
|
|
54
|
+
# Empty lists
|
|
55
|
+
assert [] < [1]
|
|
56
|
+
assert [] <= []
|
|
57
|
+
assert [1] > []
|
|
58
|
+
assert not ([] > [])
|
|
59
|
+
|
|
60
|
+
# ── 4. Nested list lexicographic ordering ────────────────────────────────────
|
|
61
|
+
|
|
62
|
+
assert [[1, 2], [3]] < [[1, 2], [4]]
|
|
63
|
+
assert [[1], [2]] < [[1], [2], []]
|
|
64
|
+
|
|
65
|
+
# ── 5. Bool operands (bool is int in Python) ─────────────────────────────────
|
|
66
|
+
|
|
67
|
+
assert not (True < True)
|
|
68
|
+
assert False < True
|
|
69
|
+
assert True > False
|
|
70
|
+
assert True >= True
|
|
71
|
+
|
|
72
|
+
# ── 6. Custom __lt__ / __le__ / __gt__ / __ge__ dispatch ────────────────────
|
|
73
|
+
|
|
74
|
+
class Vec:
|
|
75
|
+
def __init__(self, x):
|
|
76
|
+
self.x = x
|
|
77
|
+
def __lt__(self, other):
|
|
78
|
+
return self.x < other.x
|
|
79
|
+
def __le__(self, other):
|
|
80
|
+
return self.x <= other.x
|
|
81
|
+
def __gt__(self, other):
|
|
82
|
+
return self.x > other.x
|
|
83
|
+
def __ge__(self, other):
|
|
84
|
+
return self.x >= other.x
|
|
85
|
+
|
|
86
|
+
v1 = Vec(1)
|
|
87
|
+
v2 = Vec(2)
|
|
88
|
+
v3 = Vec(2)
|
|
89
|
+
|
|
90
|
+
assert v1 < v2
|
|
91
|
+
assert not (v2 < v1)
|
|
92
|
+
assert v2 > v1
|
|
93
|
+
assert not (v1 > v2)
|
|
94
|
+
assert v1 <= v2
|
|
95
|
+
assert v2 <= v3
|
|
96
|
+
assert v2 >= v3
|
|
97
|
+
assert v2 >= v1
|
|
98
|
+
assert not (v1 >= v2)
|
|
99
|
+
|
|
100
|
+
# ── 7. Reflected dunder dispatch ─────────────────────────────────────────────
|
|
101
|
+
# When left has no __gt__, Python calls right.__lt__
|
|
102
|
+
|
|
103
|
+
class LtOnly:
|
|
104
|
+
"""Only defines __lt__; reflected ops depend on the right-hand operand."""
|
|
105
|
+
def __init__(self, x):
|
|
106
|
+
self.x = x
|
|
107
|
+
def __lt__(self, other):
|
|
108
|
+
return self.x < other.x
|
|
109
|
+
|
|
110
|
+
a = LtOnly(1)
|
|
111
|
+
b = LtOnly(2)
|
|
112
|
+
|
|
113
|
+
assert a < b # a.__lt__(b)
|
|
114
|
+
assert b > a # b.__gt__ absent → ρσ_op_gt falls back → ρσ_op_lt(a, b) → a.__lt__(b)
|
|
115
|
+
|
|
116
|
+
# ── 8. TypeError for incompatible types ──────────────────────────────────────
|
|
117
|
+
|
|
118
|
+
assert _raises(def(): return 1 < 'x';, TypeError)
|
|
119
|
+
assert _raises(def(): return 'x' < 1;, TypeError)
|
|
120
|
+
assert _raises(def(): return [1] < 1;, TypeError)
|
|
121
|
+
assert _raises(def(): return 1 < [1];, TypeError)
|
|
122
|
+
assert _raises(def(): return 1 > 'x';, TypeError)
|
|
123
|
+
assert _raises(def(): return 1 <= 'x';, TypeError)
|
|
124
|
+
assert _raises(def(): return 1 >= 'x';, TypeError)
|
|
125
|
+
|
|
126
|
+
# ── 9. TypeError message contains operator symbol ────────────────────────────
|
|
127
|
+
|
|
128
|
+
def _err_msg(fn):
|
|
129
|
+
try:
|
|
130
|
+
fn()
|
|
131
|
+
except TypeError as e:
|
|
132
|
+
return str(e)
|
|
133
|
+
return ''
|
|
134
|
+
|
|
135
|
+
msg = _err_msg(def(): return 1 < 'x';)
|
|
136
|
+
assert "'<'" in msg, msg
|
|
137
|
+
assert 'int' in msg, msg
|
|
138
|
+
assert 'str' in msg, msg
|
|
139
|
+
|
|
140
|
+
msg = _err_msg(def(): return 1 > [1];)
|
|
141
|
+
assert "'>'" in msg, msg
|
|
142
|
+
|
|
143
|
+
msg = _err_msg(def(): return 1 <= {};)
|
|
144
|
+
assert "'<='" in msg, msg
|
|
145
|
+
|
|
146
|
+
msg = _err_msg(def(): return 1 >= {};)
|
|
147
|
+
assert "'>='" in msg, msg
|
|
148
|
+
|
|
149
|
+
# ── 10. Chained comparisons with overloaded ops ───────────────────────────────
|
|
150
|
+
|
|
151
|
+
assert 1 < 2 < 3
|
|
152
|
+
assert not (1 < 2 < 2)
|
|
153
|
+
assert 3 > 2 > 1
|
|
154
|
+
assert 1 <= 1 <= 2
|
|
155
|
+
assert [1] < [2] < [3]
|
|
156
|
+
assert [3] > [2] > [1]
|
|
157
|
+
|
|
158
|
+
# Mixed direction chain
|
|
159
|
+
assert 1 < 2 > 0
|
|
160
|
+
assert not (1 < 2 > 3)
|
|
161
|
+
|
|
162
|
+
# ── 11. Chained comparison: middle expression evaluated once ─────────────────
|
|
163
|
+
|
|
164
|
+
counter = [0]
|
|
165
|
+
def inc_and_return(val):
|
|
166
|
+
counter[0] += 1
|
|
167
|
+
return val
|
|
168
|
+
|
|
169
|
+
# a < inc_and_return(b) < c — middle must be evaluated exactly once
|
|
170
|
+
assert 1 < inc_and_return(2) < 3
|
|
171
|
+
assert counter[0] == 1, counter[0]
|
|
172
|
+
|
|
173
|
+
print('All comparison_ops tests passed.')
|