rapydscript-ns 0.9.2 → 0.9.4
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/CHANGELOG.md +28 -0
- package/PYTHON_GAPS.md +352 -0
- package/README.md +176 -32
- package/TODO.md +1 -128
- package/bin/rapydscript +70 -70
- package/language-service/index.js +242 -11
- package/memory/project_string_impl.md +43 -0
- package/package.json +1 -1
- 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/src/ast.pyj +10 -1
- package/src/baselib-builtins.pyj +56 -2
- package/src/baselib-containers.pyj +25 -1
- package/src/baselib-errors.pyj +7 -3
- package/src/baselib-internal.pyj +51 -6
- package/src/baselib-str.pyj +18 -5
- 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 +228 -4
- package/src/lib/csv.pyj +494 -0
- 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/logging.pyj +672 -0
- package/src/lib/pprint.pyj +455 -0
- package/src/lib/pythonize.pyj +20 -20
- package/src/lib/statistics.pyj +0 -0
- package/src/lib/string.pyj +357 -0
- package/src/lib/textwrap.pyj +329 -0
- 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/monaco-language-service/analyzer.js +5 -2
- package/src/monaco-language-service/completions.js +26 -0
- package/src/monaco-language-service/diagnostics.js +203 -4
- package/src/monaco-language-service/scope.js +1 -0
- package/src/output/codegen.pyj +4 -1
- package/src/output/functions.pyj +152 -6
- 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/parse.pyj +108 -24
- package/src/tokenizer.pyj +19 -3
- package/test/async_generators.pyj +144 -0
- package/test/asyncio.pyj +307 -0
- package/test/base64.pyj +202 -0
- package/test/baselib.pyj +23 -0
- package/test/bisect.pyj +178 -0
- package/test/chainmap.pyj +185 -0
- package/test/csv.pyj +405 -0
- package/test/float_special.pyj +64 -0
- 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/logging.pyj +356 -0
- package/test/long.pyj +130 -0
- package/test/parenthesized_with.pyj +141 -0
- package/test/pprint.pyj +232 -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/statistics.pyj +224 -0
- 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 +94 -6
- package/test/unit/language-service-completions.js +121 -0
- package/test/unit/language-service-scope.js +32 -0
- package/test/unit/language-service.js +190 -5
- package/test/unit/run-language-service.js +17 -3
- package/test/unit/web-repl.js +2401 -13
- package/test/urllib.pyj +193 -0
- package/tools/compile.js +1 -1
- package/tools/embedded_compiler.js +7 -7
- package/tools/export.js +4 -2
- package/web-repl/main.js +1 -1
- package/web-repl/rapydscript.js +7 -5
- package/test/omit_function_metadata.pyj +0 -20
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)
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
# globals: assrt
|
|
2
|
+
# vim:fileencoding=utf-8
|
|
3
|
+
#
|
|
4
|
+
# chainmap.pyj
|
|
5
|
+
# Tests for collections.ChainMap.
|
|
6
|
+
|
|
7
|
+
from __python__ import overload_getitem
|
|
8
|
+
from collections import ChainMap
|
|
9
|
+
|
|
10
|
+
ae = assrt.equal
|
|
11
|
+
ade = assrt.deepEqual
|
|
12
|
+
ok = assrt.ok
|
|
13
|
+
|
|
14
|
+
# ── 1. construction and lookup — first map wins ───────────────────────────────
|
|
15
|
+
|
|
16
|
+
defaults = {'color': 'red', 'user': 'guest', 'depth': 1}
|
|
17
|
+
overrides = {'user': 'admin'}
|
|
18
|
+
cm = ChainMap(overrides, defaults)
|
|
19
|
+
|
|
20
|
+
ae(cm['user'], 'admin') # found in first map
|
|
21
|
+
ae(cm['color'], 'red') # falls through to second map
|
|
22
|
+
ae(cm['depth'], 1)
|
|
23
|
+
ae(len(cm), 3) # unique keys across all maps
|
|
24
|
+
|
|
25
|
+
# ── 2. empty construction uses a single empty dict ────────────────────────────
|
|
26
|
+
|
|
27
|
+
empty = ChainMap()
|
|
28
|
+
ae(len(empty), 0)
|
|
29
|
+
ae(empty.maps.length, 1)
|
|
30
|
+
|
|
31
|
+
# ── 3. missing key raises KeyError ────────────────────────────────────────────
|
|
32
|
+
|
|
33
|
+
_err = False
|
|
34
|
+
try:
|
|
35
|
+
cm['missing']
|
|
36
|
+
except KeyError:
|
|
37
|
+
_err = True
|
|
38
|
+
ok(_err, 'missing key raises KeyError')
|
|
39
|
+
|
|
40
|
+
# ── 4. writes, deletes and updates affect only the first map ──────────────────
|
|
41
|
+
|
|
42
|
+
cm['depth'] = 99
|
|
43
|
+
ae(cm['depth'], 99) # shadows the value in defaults
|
|
44
|
+
ae(defaults['depth'], 1) # underlying map untouched
|
|
45
|
+
ae(overrides['depth'], 99) # written to the first map
|
|
46
|
+
|
|
47
|
+
cm['user'] = 'root'
|
|
48
|
+
ae(cm['user'], 'root')
|
|
49
|
+
|
|
50
|
+
del cm['user']
|
|
51
|
+
ae(cm['user'], 'guest') # first-map entry removed; falls through again
|
|
52
|
+
|
|
53
|
+
_del_err = False
|
|
54
|
+
try:
|
|
55
|
+
del cm['color'] # 'color' lives in the second map, not the first
|
|
56
|
+
except KeyError:
|
|
57
|
+
_del_err = True
|
|
58
|
+
ok(_del_err, 'deleting a key absent from the first map raises KeyError')
|
|
59
|
+
|
|
60
|
+
# ── 5. membership, get, and iteration ─────────────────────────────────────────
|
|
61
|
+
|
|
62
|
+
ok('color' in cm)
|
|
63
|
+
ok('user' in cm)
|
|
64
|
+
ok('nope' not in cm)
|
|
65
|
+
ae(cm.get('color'), 'red')
|
|
66
|
+
ae(cm.get('nope'), None)
|
|
67
|
+
ae(cm.get('nope', 'fallback'), 'fallback')
|
|
68
|
+
|
|
69
|
+
m1 = {'a': 1, 'b': 2}
|
|
70
|
+
m2 = {'c': 3}
|
|
71
|
+
ordered = ChainMap(m1, m2)
|
|
72
|
+
ade(list(ordered), ['c', 'a', 'b']) # Python order: later maps first
|
|
73
|
+
ade(ordered.keys(), ['c', 'a', 'b'])
|
|
74
|
+
ade(ordered.values(), [3, 1, 2])
|
|
75
|
+
ade(ordered.items(), [['c', 3], ['a', 1], ['b', 2]])
|
|
76
|
+
|
|
77
|
+
_seen = []
|
|
78
|
+
for k in ordered:
|
|
79
|
+
_seen.push(k)
|
|
80
|
+
ade(_seen, ['c', 'a', 'b'])
|
|
81
|
+
|
|
82
|
+
# ── 6. maps attribute, new_child and parents ──────────────────────────────────
|
|
83
|
+
|
|
84
|
+
base = ChainMap({'x': 1})
|
|
85
|
+
child = base.new_child({'x': 2, 'y': 3})
|
|
86
|
+
ae(child['x'], 2) # child's own map shadows the parent
|
|
87
|
+
ae(child['y'], 3)
|
|
88
|
+
ae(base['x'], 1) # parent unchanged
|
|
89
|
+
ae(child.maps.length, 2)
|
|
90
|
+
|
|
91
|
+
# new_child() with no argument adds a fresh empty map
|
|
92
|
+
fresh = base.new_child()
|
|
93
|
+
ae(fresh.maps.length, 2)
|
|
94
|
+
ae(len(fresh), 1)
|
|
95
|
+
fresh['z'] = 7
|
|
96
|
+
ae(fresh['z'], 7)
|
|
97
|
+
ok('z' not in base)
|
|
98
|
+
|
|
99
|
+
# parents drops the first map
|
|
100
|
+
parents = child.parents
|
|
101
|
+
ae(parents['x'], 1)
|
|
102
|
+
ae(parents.maps.length, 1)
|
|
103
|
+
|
|
104
|
+
# ── 7. copy is shallow — first map cloned, rest shared ────────────────────────
|
|
105
|
+
|
|
106
|
+
src = ChainMap({'a': 1}, {'b': 2})
|
|
107
|
+
dup = src.copy()
|
|
108
|
+
dup['a'] = 100
|
|
109
|
+
ae(src['a'], 1) # first map was cloned
|
|
110
|
+
dup['c'] = 9 # writes to the cloned first map
|
|
111
|
+
ok('c' not in src)
|
|
112
|
+
ae(dup['b'], 2) # tail maps are shared
|
|
113
|
+
|
|
114
|
+
# ── 8. pop, popitem, clear, setdefault, update ────────────────────────────────
|
|
115
|
+
|
|
116
|
+
p = ChainMap({'a': 1, 'b': 2}, {'c': 3})
|
|
117
|
+
ae(p.pop('a'), 1)
|
|
118
|
+
ok('a' not in p.maps[0])
|
|
119
|
+
ae(p.pop('missing', 'dflt'), 'dflt')
|
|
120
|
+
|
|
121
|
+
_pop_err = False
|
|
122
|
+
try:
|
|
123
|
+
p.pop('c') # 'c' is not in the first map
|
|
124
|
+
except KeyError:
|
|
125
|
+
_pop_err = True
|
|
126
|
+
ok(_pop_err, 'pop of a key absent from the first map raises KeyError')
|
|
127
|
+
|
|
128
|
+
pi = ChainMap({'only': 42})
|
|
129
|
+
ade(pi.popitem(), ['only', 42])
|
|
130
|
+
ae(len(pi.maps[0]), 0)
|
|
131
|
+
|
|
132
|
+
sd = ChainMap({'a': 1}, {'b': 2})
|
|
133
|
+
ae(sd.setdefault('a', 999), 1) # existing key — unchanged
|
|
134
|
+
ae(sd.setdefault('new', 5), 5) # missing key — inserted into first map
|
|
135
|
+
ae(sd['new'], 5)
|
|
136
|
+
ae(sd.setdefault('b', 0), 2) # found in tail map — not copied forward
|
|
137
|
+
ok('b' not in sd.maps[0])
|
|
138
|
+
|
|
139
|
+
up = ChainMap({'a': 1}, {'b': 2})
|
|
140
|
+
up.update({'a': 10, 'd': 4})
|
|
141
|
+
ae(up['a'], 10)
|
|
142
|
+
ae(up['d'], 4)
|
|
143
|
+
up.update(e=5)
|
|
144
|
+
ae(up['e'], 5)
|
|
145
|
+
up.update([['f', 6]])
|
|
146
|
+
ae(up['f'], 6)
|
|
147
|
+
|
|
148
|
+
cl = ChainMap({'a': 1, 'b': 2}, {'c': 3})
|
|
149
|
+
cl.clear()
|
|
150
|
+
ae(len(cl.maps[0]), 0)
|
|
151
|
+
ae(cl['c'], 3) # tail map survives clear()
|
|
152
|
+
|
|
153
|
+
# ── 9. nested ChainMap as a member map ────────────────────────────────────────
|
|
154
|
+
|
|
155
|
+
inner = ChainMap({'a': 1}, {'b': 2})
|
|
156
|
+
outer = ChainMap({'c': 3}, inner)
|
|
157
|
+
ae(outer['a'], 1)
|
|
158
|
+
ae(outer['b'], 2)
|
|
159
|
+
ae(outer['c'], 3)
|
|
160
|
+
ok('a' in outer)
|
|
161
|
+
ae(len(outer), 3)
|
|
162
|
+
|
|
163
|
+
# ── 10. equality ──────────────────────────────────────────────────────────────
|
|
164
|
+
|
|
165
|
+
ok(ChainMap({'a': 1}, {'b': 2}) == ChainMap({'a': 1}, {'b': 2}))
|
|
166
|
+
ok(ChainMap({'a': 1}) == {'a': 1})
|
|
167
|
+
ok(not (ChainMap({'a': 1}) == ChainMap({'a': 2})))
|
|
168
|
+
ok(not (ChainMap({'a': 1}) == {'a': 1, 'b': 2}))
|
|
169
|
+
|
|
170
|
+
# ── 11. repr ──────────────────────────────────────────────────────────────────
|
|
171
|
+
|
|
172
|
+
# RapydScript's repr() quotes strings with double quotes (as Counter/OrderedDict do)
|
|
173
|
+
ae(ChainMap({'a': 1}, {'b': 2}).__repr__(), 'ChainMap({"a": 1}, {"b": 2})')
|
|
174
|
+
|
|
175
|
+
# ── 12. dynamic — changes to underlying maps are visible ──────────────────────
|
|
176
|
+
|
|
177
|
+
live = {'k': 'v1'}
|
|
178
|
+
dyn = ChainMap({}, live)
|
|
179
|
+
ae(dyn['k'], 'v1')
|
|
180
|
+
live['k'] = 'v2'
|
|
181
|
+
ae(dyn['k'], 'v2') # ChainMap reflects the mutation
|
|
182
|
+
live['extra'] = 'x'
|
|
183
|
+
ok('extra' in dyn)
|
|
184
|
+
|
|
185
|
+
print('chainmap tests passed')
|