rapydscript-ns 0.9.2 → 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.
- package/.agignore +1 -1
- package/.github/workflows/ci.yml +38 -38
- package/=template.pyj +5 -5
- package/CHANGELOG.md +19 -0
- package/HACKING.md +103 -103
- package/LICENSE +24 -24
- package/PYTHON_GAPS.md +420 -0
- package/README.md +153 -29
- package/TODO.md +16 -118
- 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 +237 -8
- package/memory/project_string_impl.md +43 -0
- package/package.json +1 -1
- package/publish.py +37 -37
- package/release/baselib-plain-pretty.js +248 -38
- package/release/baselib-plain-ugly.js +8 -8
- package/release/compiler.js +778 -277
- package/release/signatures.json +30 -30
- package/session.vim +4 -4
- package/setup.cfg +2 -2
- package/src/ast.pyj +4 -1
- package/src/baselib-builtins.pyj +56 -2
- package/src/baselib-containers.pyj +2 -0
- package/src/baselib-errors.pyj +7 -3
- package/src/baselib-internal.pyj +51 -6
- package/src/baselib-str.pyj +5 -3
- package/src/compiler.pyj +36 -36
- package/src/errors.pyj +30 -30
- package/src/lib/aes.pyj +646 -646
- package/src/lib/asyncio.pyj +534 -0
- package/src/lib/base64.pyj +399 -0
- package/src/lib/bisect.pyj +73 -0
- package/src/lib/collections.pyj +1 -1
- package/src/lib/copy.pyj +120 -120
- package/src/lib/csv.pyj +494 -0
- package/src/lib/elementmaker.pyj +83 -83
- package/src/lib/encodings.pyj +126 -126
- package/src/lib/gettext.pyj +569 -569
- package/src/lib/heapq.pyj +98 -0
- package/src/lib/html.pyj +382 -0
- package/src/lib/http/__init__.pyj +98 -0
- package/src/lib/http/client.pyj +304 -0
- package/src/lib/http/cookies.pyj +236 -0
- package/src/lib/itertools.pyj +580 -580
- package/src/lib/logging.pyj +672 -0
- 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/react.pyj +74 -74
- package/src/lib/string.pyj +357 -0
- package/src/lib/textwrap.pyj +329 -0
- package/src/lib/traceback.pyj +63 -63
- package/src/lib/urllib/__init__.pyj +14 -0
- package/src/lib/urllib/error.pyj +66 -0
- package/src/lib/urllib/parse.pyj +475 -0
- package/src/lib/urllib/request.pyj +86 -0
- package/src/lib/uuid.pyj +77 -77
- package/src/monaco-language-service/analyzer.js +5 -2
- package/src/monaco-language-service/completions.js +26 -0
- package/src/monaco-language-service/diagnostics.js +202 -3
- package/src/monaco-language-service/dts.js +550 -550
- package/src/monaco-language-service/scope.js +1 -0
- package/src/output/comments.pyj +45 -45
- package/src/output/exceptions.pyj +201 -201
- package/src/output/functions.pyj +152 -6
- package/src/output/jsx.pyj +164 -164
- package/src/output/loops.pyj +17 -2
- package/src/output/modules.pyj +1 -1
- package/src/output/operators.pyj +15 -0
- package/src/output/stream.pyj +0 -1
- package/src/output/treeshake.pyj +182 -182
- package/src/output/utils.pyj +72 -72
- package/src/parse.pyj +80 -17
- package/src/string_interpolation.pyj +72 -72
- package/src/tokenizer.pyj +1 -1
- package/src/unicode_aliases.pyj +576 -576
- package/src/utils.pyj +192 -192
- package/test/_import_one.pyj +37 -37
- package/test/_import_two/__init__.pyj +11 -11
- package/test/_import_two/level2/deep.pyj +4 -4
- package/test/_import_two/other.pyj +6 -6
- package/test/_import_two/sub.pyj +13 -13
- package/test/aes_vectors.pyj +421 -421
- package/test/annotations.pyj +80 -80
- package/test/async_generators.pyj +144 -0
- package/test/asyncio.pyj +307 -0
- package/test/base64.pyj +202 -0
- package/test/bisect.pyj +178 -0
- package/test/csv.pyj +405 -0
- package/test/decorators.pyj +77 -77
- package/test/docstrings.pyj +39 -39
- package/test/elementmaker_test.pyj +45 -45
- package/test/float_special.pyj +64 -0
- package/test/functions.pyj +151 -151
- package/test/generators.pyj +41 -41
- package/test/generic.pyj +370 -370
- package/test/heapq.pyj +174 -0
- package/test/html.pyj +212 -0
- package/test/http.pyj +259 -0
- package/test/imports.pyj +79 -72
- package/test/internationalization.pyj +73 -73
- package/test/lint.pyj +164 -164
- package/test/logging.pyj +356 -0
- package/test/long.pyj +130 -0
- package/test/loops.pyj +85 -85
- package/test/numpy.pyj +734 -734
- package/test/parenthesized_with.pyj +141 -0
- package/test/python_compat.pyj +3 -5
- package/test/python_modulo.pyj +76 -0
- package/test/python_modulo_off.pyj +21 -0
- package/test/repl.pyj +121 -121
- package/test/scoped_flags.pyj +76 -76
- package/test/str.pyj +14 -0
- package/test/string.pyj +245 -0
- package/test/textwrap.pyj +172 -0
- package/test/type_display.pyj +48 -0
- package/test/type_enforcement.pyj +164 -0
- package/test/unit/index.js +14 -6
- package/test/unit/language-service-completions.js +119 -0
- package/test/unit/language-service-dts.js +543 -543
- package/test/unit/language-service-hover.js +455 -455
- package/test/unit/language-service-scope.js +32 -0
- package/test/unit/language-service.js +127 -3
- package/test/unit/run-language-service.js +17 -3
- package/test/unit/web-repl.js +2094 -29
- package/test/urllib.pyj +193 -0
- package/tools/compile.js +1 -1
- package/tools/compiler.d.ts +367 -367
- package/tools/completer.js +131 -131
- package/tools/embedded_compiler.js +7 -7
- package/tools/gettext.js +185 -185
- package/tools/ini.js +65 -65
- package/tools/msgfmt.js +187 -187
- package/tools/repl.js +223 -223
- package/tools/test.js +118 -118
- package/tools/utils.js +128 -128
- package/tools/web_repl.js +95 -95
- package/try +41 -41
- package/web-repl/env.js +196 -196
- package/web-repl/index.html +163 -163
- package/web-repl/main.js +1 -1
- 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/test/omit_function_metadata.pyj +0 -20
package/test/base64.pyj
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
# globals: assrt
|
|
2
|
+
# vim:fileencoding=utf-8
|
|
3
|
+
#
|
|
4
|
+
# base64.pyj
|
|
5
|
+
# Tests for the base64 standard library module.
|
|
6
|
+
|
|
7
|
+
from base64 import b64encode, b64decode, standard_b64encode, standard_b64decode
|
|
8
|
+
from base64 import urlsafe_b64encode, urlsafe_b64decode
|
|
9
|
+
from base64 import b32encode, b32decode
|
|
10
|
+
from base64 import b16encode, b16decode
|
|
11
|
+
from base64 import encodebytes, decodebytes
|
|
12
|
+
from base64 import Error
|
|
13
|
+
|
|
14
|
+
ae = assrt.equal
|
|
15
|
+
ade = assrt.deepEqual
|
|
16
|
+
ok = assrt.ok
|
|
17
|
+
throws = assrt.throws
|
|
18
|
+
|
|
19
|
+
# Helper: convert bytes to ASCII string for easy comparison
|
|
20
|
+
def _str(b):
|
|
21
|
+
return b.decode('ascii')
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
# ── 1. b64encode — basic round-trips ─────────────────────────────────────────
|
|
25
|
+
|
|
26
|
+
ae(_str(b64encode(bytes([]))), '')
|
|
27
|
+
ae(_str(b64encode(bytes([0]))), 'AA==')
|
|
28
|
+
ae(_str(b64encode(bytes([0, 0]))), 'AAA=')
|
|
29
|
+
ae(_str(b64encode(bytes([0, 0, 0]))), 'AAAA')
|
|
30
|
+
ae(_str(b64encode(bytes([77, 97, 110]))), 'TWFu') # 'Man'
|
|
31
|
+
|
|
32
|
+
# Known Python vectors
|
|
33
|
+
ae(_str(b64encode(bytes([104, 101, 108, 108, 111]))), 'aGVsbG8=') # 'hello'
|
|
34
|
+
ae(_str(b64encode(bytes([104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100]))), 'aGVsbG8gd29ybGQ=') # 'hello world'
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
# ── 2. b64decode ──────────────────────────────────────────────────────────────
|
|
38
|
+
|
|
39
|
+
_dec1 = b64decode('TWFu')
|
|
40
|
+
ade(list(_dec1), [77, 97, 110])
|
|
41
|
+
|
|
42
|
+
_dec2 = b64decode('aGVsbG8=')
|
|
43
|
+
ade(list(_dec2), [104, 101, 108, 108, 111])
|
|
44
|
+
|
|
45
|
+
# Empty string
|
|
46
|
+
ade(list(b64decode('')), [])
|
|
47
|
+
|
|
48
|
+
# Missing padding — Python strips whitespace and pads internally
|
|
49
|
+
_dec3 = b64decode('aGVsbG8')
|
|
50
|
+
ade(list(_dec3), [104, 101, 108, 108, 111])
|
|
51
|
+
|
|
52
|
+
# With embedded whitespace (stripped by default)
|
|
53
|
+
_dec4 = b64decode('aGVs bG8=')
|
|
54
|
+
ade(list(_dec4), [104, 101, 108, 108, 111])
|
|
55
|
+
|
|
56
|
+
# Accepts bytes input
|
|
57
|
+
_dec5 = b64decode(bytes([84, 87, 70, 117])) # b'TWFu'
|
|
58
|
+
ade(list(_dec5), [77, 97, 110])
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
# ── 3. b64encode / b64decode with altchars ────────────────────────────────────
|
|
62
|
+
|
|
63
|
+
# altchars b'-_': replaces + and /
|
|
64
|
+
_enc_alt = b64encode(bytes([251, 239, 190]), altchars=bytes([45, 95])) # b'-_'
|
|
65
|
+
_enc_std = b64encode(bytes([251, 239, 190]))
|
|
66
|
+
ok(_str(_enc_alt).indexOf('-') >= 0 or _str(_enc_alt).indexOf('_') >= 0
|
|
67
|
+
or (_str(_enc_alt) == _str(_enc_std)),
|
|
68
|
+
'altchars encoding should differ or be identical if no + or / present')
|
|
69
|
+
|
|
70
|
+
# Round-trip with altchars
|
|
71
|
+
_data_alt = bytes([200, 100, 50, 25])
|
|
72
|
+
_enc2 = b64encode(_data_alt, altchars=bytes([45, 95]))
|
|
73
|
+
_dec6 = b64decode(_enc2, altchars=bytes([45, 95]))
|
|
74
|
+
ade(list(_dec6), list(_data_alt))
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
# ── 4. standard_b64encode / standard_b64decode ────────────────────────────────
|
|
78
|
+
|
|
79
|
+
_s_enc = standard_b64encode(bytes([104, 101, 108, 108, 111]))
|
|
80
|
+
ae(_str(_s_enc), 'aGVsbG8=')
|
|
81
|
+
|
|
82
|
+
_s_dec = standard_b64decode('aGVsbG8=')
|
|
83
|
+
ade(list(_s_dec), [104, 101, 108, 108, 111])
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
# ── 5. urlsafe_b64encode / urlsafe_b64decode ──────────────────────────────────
|
|
87
|
+
|
|
88
|
+
# bytes([251, 239, 190]) encodes to '----' in URL-safe (all 6-bit groups are 62)
|
|
89
|
+
_us_enc = urlsafe_b64encode(bytes([251, 239, 190]))
|
|
90
|
+
ok(_str(_us_enc).indexOf('+') < 0, 'URL-safe should not contain +')
|
|
91
|
+
ok(_str(_us_enc).indexOf('/') < 0, 'URL-safe should not contain /')
|
|
92
|
+
ae(_str(_us_enc), '----')
|
|
93
|
+
|
|
94
|
+
# Round-trip with data that produces + and / in standard encoding
|
|
95
|
+
_us_data = bytes([251, 254, 254]) # encodes to '-_7-' in URL-safe
|
|
96
|
+
_us_enc2 = urlsafe_b64encode(_us_data)
|
|
97
|
+
ae(_str(_us_enc2), '-_7-')
|
|
98
|
+
|
|
99
|
+
# URL-safe decode
|
|
100
|
+
_us_dec = urlsafe_b64decode('-_7-')
|
|
101
|
+
ade(list(_us_dec), [251, 254, 254])
|
|
102
|
+
|
|
103
|
+
# Round-trip with general data
|
|
104
|
+
_us_rt_data = bytes([0, 1, 2, 127, 128, 255])
|
|
105
|
+
_us_rt = urlsafe_b64decode(urlsafe_b64encode(_us_rt_data))
|
|
106
|
+
ade(list(_us_rt), list(_us_rt_data))
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
# ── 6. b32encode / b32decode ─────────────────────────────────────────────────
|
|
110
|
+
|
|
111
|
+
ae(_str(b32encode(bytes([]))), '')
|
|
112
|
+
ae(_str(b32encode(bytes([102]))), 'MY======') # b'f' → 'MY======'
|
|
113
|
+
ae(_str(b32encode(bytes([102, 111]))), 'MZXQ====') # b'fo' → 'MZXQ===='
|
|
114
|
+
ae(_str(b32encode(bytes([102, 111, 111]))), 'MZXW6===') # b'foo'
|
|
115
|
+
ae(_str(b32encode(bytes([102, 111, 111, 98]))), 'MZXW6YQ=') # b'foob'
|
|
116
|
+
ae(_str(b32encode(bytes([102, 111, 111, 98, 97]))), 'MZXW6YTB') # b'fooba'
|
|
117
|
+
|
|
118
|
+
# Round-trip several lengths
|
|
119
|
+
for _rt_data in [bytes([]), bytes([42]), bytes([1, 2, 3]), bytes([255, 0, 128, 64])]:
|
|
120
|
+
ade(list(b32decode(b32encode(_rt_data))), list(_rt_data))
|
|
121
|
+
|
|
122
|
+
# casefold
|
|
123
|
+
_b32_lc = b32decode('mzxw6ytb', casefold=True)
|
|
124
|
+
ade(list(_b32_lc), list(bytes([102, 111, 111, 98, 97])))
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
# ── 7. b16encode / b16decode ──────────────────────────────────────────────────
|
|
128
|
+
|
|
129
|
+
ae(_str(b16encode(bytes([]))), '')
|
|
130
|
+
ae(_str(b16encode(bytes([0]))), '00')
|
|
131
|
+
ae(_str(b16encode(bytes([255]))), 'FF')
|
|
132
|
+
ae(_str(b16encode(bytes([0, 1, 254, 255]))), '0001FEFF')
|
|
133
|
+
ae(_str(b16encode(bytes([171]))), 'AB')
|
|
134
|
+
|
|
135
|
+
# Round-trip
|
|
136
|
+
ade(list(b16decode(b16encode(bytes([10, 20, 30, 40, 250])))), [10, 20, 30, 40, 250])
|
|
137
|
+
|
|
138
|
+
# casefold
|
|
139
|
+
ade(list(b16decode('0001feff', casefold=True)), [0, 1, 254, 255])
|
|
140
|
+
|
|
141
|
+
# Error on invalid hex
|
|
142
|
+
_b16_err = False
|
|
143
|
+
try:
|
|
144
|
+
b16decode('ZZ')
|
|
145
|
+
except Error:
|
|
146
|
+
_b16_err = True
|
|
147
|
+
ok(_b16_err, 'b16decode of non-hex should raise Error')
|
|
148
|
+
|
|
149
|
+
# Error on odd-length string
|
|
150
|
+
_b16_odd = False
|
|
151
|
+
try:
|
|
152
|
+
b16decode('A')
|
|
153
|
+
except Error:
|
|
154
|
+
_b16_odd = True
|
|
155
|
+
ok(_b16_odd, 'b16decode of odd-length string should raise Error')
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
# ── 8. encodebytes / decodebytes ──────────────────────────────────────────────
|
|
159
|
+
|
|
160
|
+
# encodebytes wraps at 76 chars per line
|
|
161
|
+
_long_data = bytes(list(range(57))) # 57 bytes → exactly 76 base64 chars (one line)
|
|
162
|
+
_enc_lines = encodebytes(_long_data)
|
|
163
|
+
_enc_lines_str = _str(_enc_lines)
|
|
164
|
+
# Each line ends with \n
|
|
165
|
+
ok(_enc_lines_str[-1:] == '\n', 'encodebytes output should end with newline')
|
|
166
|
+
|
|
167
|
+
# Decode should recover original
|
|
168
|
+
_dec_lines = decodebytes(_enc_lines)
|
|
169
|
+
ade(list(_dec_lines), list(_long_data))
|
|
170
|
+
|
|
171
|
+
# More than 57 bytes → multiple lines
|
|
172
|
+
_long2 = bytes(list(range(100)))
|
|
173
|
+
_enc2b = encodebytes(_long2)
|
|
174
|
+
ok(_str(_enc2b).split('\n').length > 2, 'long encodebytes should have multiple lines')
|
|
175
|
+
ade(list(decodebytes(_enc2b)), list(_long2))
|
|
176
|
+
|
|
177
|
+
# Empty bytes
|
|
178
|
+
ade(list(decodebytes(encodebytes(bytes([])))), [])
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
# ── 9. b64decode validate=True ────────────────────────────────────────────────
|
|
182
|
+
|
|
183
|
+
# Valid input should not raise
|
|
184
|
+
_valid = b64decode('aGVsbG8=', validate=True)
|
|
185
|
+
ade(list(_valid), [104, 101, 108, 108, 111])
|
|
186
|
+
|
|
187
|
+
# Invalid character raises Error when validate=True
|
|
188
|
+
_bad_raised = False
|
|
189
|
+
try:
|
|
190
|
+
b64decode('aGVs!G8=', validate=True)
|
|
191
|
+
except Error:
|
|
192
|
+
_bad_raised = True
|
|
193
|
+
ok(_bad_raised, 'validate=True should raise Error on non-base64 character')
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
# ── 10. b64encode returns bytes ───────────────────────────────────────────────
|
|
197
|
+
|
|
198
|
+
_enc_type = b64encode(bytes([1, 2, 3]))
|
|
199
|
+
ok(isinstance(_enc_type, bytes), 'b64encode should return bytes')
|
|
200
|
+
|
|
201
|
+
_dec_type = b64decode('AQID')
|
|
202
|
+
ok(isinstance(_dec_type, bytes), 'b64decode should return bytes')
|
package/test/bisect.pyj
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
# globals: assrt
|
|
2
|
+
# vim:fileencoding=utf-8
|
|
3
|
+
#
|
|
4
|
+
# bisect.pyj
|
|
5
|
+
# Tests for the bisect standard library module.
|
|
6
|
+
|
|
7
|
+
from bisect import bisect_left, bisect_right, bisect, insort_left, insort_right, insort
|
|
8
|
+
|
|
9
|
+
ae = assrt.equal
|
|
10
|
+
ade = assrt.deepEqual
|
|
11
|
+
ok = assrt.ok
|
|
12
|
+
|
|
13
|
+
# ── 1. bisect_left — basic ────────────────────────────────────────────────────
|
|
14
|
+
|
|
15
|
+
_a = [1, 3, 5, 7, 9]
|
|
16
|
+
|
|
17
|
+
ae(bisect_left(_a, 0), 0) # before all
|
|
18
|
+
ae(bisect_left(_a, 1), 0) # at first element (left of existing)
|
|
19
|
+
ae(bisect_left(_a, 2), 1) # between 1 and 3
|
|
20
|
+
ae(bisect_left(_a, 3), 1) # at existing element (left)
|
|
21
|
+
ae(bisect_left(_a, 5), 2)
|
|
22
|
+
ae(bisect_left(_a, 6), 3) # between 5 and 7
|
|
23
|
+
ae(bisect_left(_a, 9), 4) # at last element (left)
|
|
24
|
+
ae(bisect_left(_a, 10), 5) # after all
|
|
25
|
+
|
|
26
|
+
# ── 2. bisect_right — basic ───────────────────────────────────────────────────
|
|
27
|
+
|
|
28
|
+
ae(bisect_right(_a, 0), 0) # before all
|
|
29
|
+
ae(bisect_right(_a, 1), 1) # at first element (right of existing)
|
|
30
|
+
ae(bisect_right(_a, 2), 1) # between 1 and 3
|
|
31
|
+
ae(bisect_right(_a, 3), 2) # at existing element (right)
|
|
32
|
+
ae(bisect_right(_a, 5), 3)
|
|
33
|
+
ae(bisect_right(_a, 6), 3) # between 5 and 7
|
|
34
|
+
ae(bisect_right(_a, 9), 5) # at last element (right)
|
|
35
|
+
ae(bisect_right(_a, 10), 5) # after all
|
|
36
|
+
|
|
37
|
+
# ── 3. bisect alias ───────────────────────────────────────────────────────────
|
|
38
|
+
|
|
39
|
+
ae(bisect(_a, 3), bisect_right(_a, 3))
|
|
40
|
+
ae(bisect(_a, 5), bisect_right(_a, 5))
|
|
41
|
+
|
|
42
|
+
# ── 4. Empty list ─────────────────────────────────────────────────────────────
|
|
43
|
+
|
|
44
|
+
ae(bisect_left([], 5), 0)
|
|
45
|
+
ae(bisect_right([], 5), 0)
|
|
46
|
+
|
|
47
|
+
# ── 5. All elements equal ─────────────────────────────────────────────────────
|
|
48
|
+
|
|
49
|
+
_eq = [3, 3, 3, 3, 3]
|
|
50
|
+
ae(bisect_left(_eq, 3), 0)
|
|
51
|
+
ae(bisect_right(_eq, 3), 5)
|
|
52
|
+
ae(bisect_left(_eq, 2), 0)
|
|
53
|
+
ae(bisect_right(_eq, 2), 0)
|
|
54
|
+
ae(bisect_left(_eq, 4), 5)
|
|
55
|
+
ae(bisect_right(_eq, 4), 5)
|
|
56
|
+
|
|
57
|
+
# ── 6. Single-element list ────────────────────────────────────────────────────
|
|
58
|
+
|
|
59
|
+
_one = [5]
|
|
60
|
+
ae(bisect_left(_one, 5), 0)
|
|
61
|
+
ae(bisect_right(_one, 5), 1)
|
|
62
|
+
ae(bisect_left(_one, 4), 0)
|
|
63
|
+
ae(bisect_right(_one, 6), 1)
|
|
64
|
+
|
|
65
|
+
# ── 7. lo and hi bounds ───────────────────────────────────────────────────────
|
|
66
|
+
|
|
67
|
+
_b = [1, 3, 5, 7, 9]
|
|
68
|
+
# search only in [3, 5, 7] (indices 1..3)
|
|
69
|
+
ae(bisect_left(_b, 3, 1, 4), 1)
|
|
70
|
+
ae(bisect_right(_b, 3, 1, 4), 2)
|
|
71
|
+
ae(bisect_left(_b, 6, 1, 4), 3)
|
|
72
|
+
|
|
73
|
+
# lo == hi: insertion point is lo regardless of x
|
|
74
|
+
ae(bisect_left(_b, 5, 2, 2), 2)
|
|
75
|
+
ae(bisect_right(_b, 5, 2, 2), 2)
|
|
76
|
+
|
|
77
|
+
# ── 8. ValueError for negative lo ────────────────────────────────────────────
|
|
78
|
+
|
|
79
|
+
_neg_lo_raised = False
|
|
80
|
+
try:
|
|
81
|
+
bisect_left([1, 2], 1, -1)
|
|
82
|
+
except ValueError:
|
|
83
|
+
_neg_lo_raised = True
|
|
84
|
+
ok(_neg_lo_raised, 'bisect_left with negative lo should raise ValueError')
|
|
85
|
+
|
|
86
|
+
_neg_lo_raised2 = False
|
|
87
|
+
try:
|
|
88
|
+
bisect_right([1, 2], 1, -1)
|
|
89
|
+
except ValueError:
|
|
90
|
+
_neg_lo_raised2 = True
|
|
91
|
+
ok(_neg_lo_raised2, 'bisect_right with negative lo should raise ValueError')
|
|
92
|
+
|
|
93
|
+
# ── 9. insort_left — basic ────────────────────────────────────────────────────
|
|
94
|
+
|
|
95
|
+
_il = [1, 3, 5, 7]
|
|
96
|
+
insort_left(_il, 4)
|
|
97
|
+
ade(_il, [1, 3, 4, 5, 7])
|
|
98
|
+
|
|
99
|
+
insort_left(_il, 3) # insert at left of equal elements
|
|
100
|
+
ae(_il[1], 3)
|
|
101
|
+
ae(_il[2], 3)
|
|
102
|
+
ae(_il.length, 6)
|
|
103
|
+
|
|
104
|
+
# ── 10. insort_right — basic ──────────────────────────────────────────────────
|
|
105
|
+
|
|
106
|
+
_ir = [1, 3, 5, 7]
|
|
107
|
+
insort_right(_ir, 4)
|
|
108
|
+
ade(_ir, [1, 3, 4, 5, 7])
|
|
109
|
+
|
|
110
|
+
insort_right(_ir, 3) # insert at right of equal elements — new 3 goes at index 2
|
|
111
|
+
ade(_ir, [1, 3, 3, 4, 5, 7])
|
|
112
|
+
ae(_ir.length, 6)
|
|
113
|
+
|
|
114
|
+
# ── 11. insort alias ──────────────────────────────────────────────────────────
|
|
115
|
+
|
|
116
|
+
_ins = [2, 4, 6]
|
|
117
|
+
insort(_ins, 5)
|
|
118
|
+
ade(_ins, [2, 4, 5, 6])
|
|
119
|
+
|
|
120
|
+
# ── 12. insort builds a sorted list from scratch ──────────────────────────────
|
|
121
|
+
|
|
122
|
+
_scratch = []
|
|
123
|
+
for _v in [5, 1, 3, 2, 4]:
|
|
124
|
+
insort(_scratch, _v)
|
|
125
|
+
ade(_scratch, [1, 2, 3, 4, 5])
|
|
126
|
+
|
|
127
|
+
# ── 13. Strings (lexicographic) ───────────────────────────────────────────────
|
|
128
|
+
|
|
129
|
+
_s = ['bar', 'baz', 'foo', 'qux']
|
|
130
|
+
ae(bisect_left(_s, 'baz'), 1)
|
|
131
|
+
ae(bisect_right(_s, 'baz'), 2)
|
|
132
|
+
ae(bisect_left(_s, 'car'), 2) # 'car' > 'baz' and < 'foo'
|
|
133
|
+
ae(bisect_right(_s, 'car'), 2)
|
|
134
|
+
|
|
135
|
+
# ── 14. key function — bisect_left / bisect_right ────────────────────────────
|
|
136
|
+
|
|
137
|
+
# list of pairs sorted by first element; search by first element
|
|
138
|
+
_pairs = [[1, 'a'], [3, 'b'], [5, 'c'], [7, 'd']]
|
|
139
|
+
_kfn = def(item): return item[0];
|
|
140
|
+
|
|
141
|
+
ae(bisect_left(_pairs, 3, 0, None, _kfn), 1)
|
|
142
|
+
ae(bisect_right(_pairs, 3, 0, None, _kfn), 2)
|
|
143
|
+
ae(bisect_left(_pairs, 4, 0, None, _kfn), 2)
|
|
144
|
+
ae(bisect_right(_pairs, 4, 0, None, _kfn), 2)
|
|
145
|
+
ae(bisect_left(_pairs, 0, 0, None, _kfn), 0)
|
|
146
|
+
ae(bisect_right(_pairs, 8, 0, None, _kfn), 4)
|
|
147
|
+
|
|
148
|
+
# ── 15. insort with lo/hi bounds ─────────────────────────────────────────────
|
|
149
|
+
# Only the sub-slice [10, 20, 30] (indices 3..5) is searched;
|
|
150
|
+
# 15 is inserted at index 4, between 10 and 20.
|
|
151
|
+
|
|
152
|
+
_bounded = [1, 2, 3, 10, 20, 30]
|
|
153
|
+
insort_right(_bounded, 15, 3, 6)
|
|
154
|
+
ade(_bounded, [1, 2, 3, 10, 15, 20, 30])
|
|
155
|
+
|
|
156
|
+
_bounded2 = [1, 2, 3, 10, 20, 30]
|
|
157
|
+
insort_left(_bounded2, 20, 3, 6) # left of existing 20
|
|
158
|
+
ae(_bounded2[4], 20)
|
|
159
|
+
ae(_bounded2[5], 20)
|
|
160
|
+
ae(_bounded2.length, 7)
|
|
161
|
+
|
|
162
|
+
# ── 16. Duplicate-value stability ────────────────────────────────────────────
|
|
163
|
+
|
|
164
|
+
_dup = [1, 2, 2, 2, 3]
|
|
165
|
+
ae(bisect_left(_dup, 2), 1)
|
|
166
|
+
ae(bisect_right(_dup, 2), 4)
|
|
167
|
+
|
|
168
|
+
_dl = [1, 2, 2, 3]
|
|
169
|
+
insort_left(_dl, 2)
|
|
170
|
+
# new 2 inserted at index 1 (leftmost)
|
|
171
|
+
ae(_dl[1], 2)
|
|
172
|
+
ae(_dl.length, 5)
|
|
173
|
+
|
|
174
|
+
_dr = [1, 2, 2, 3]
|
|
175
|
+
insort_right(_dr, 2)
|
|
176
|
+
# new 2 inserted at index 3 (rightmost)
|
|
177
|
+
ae(_dr[3], 2)
|
|
178
|
+
ae(_dr.length, 5)
|