rapydscript-ns 0.9.3 → 0.9.5
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/PYTHON_GAPS.md +52 -142
- package/README.md +51 -21
- package/TODO.md +1 -26
- package/add-toc-to-readme +2 -2
- package/bin/export +75 -75
- package/bin/rapydscript +0 -0
- package/bin/web-repl-export +102 -102
- package/build +2 -2
- package/language-service/index.js +88 -36
- package/package.json +1 -1
- package/publish.py +37 -37
- package/release/baselib-plain-pretty.js +157 -31
- package/release/baselib-plain-ugly.js +5 -5
- package/release/compiler.js +724 -426
- package/release/signatures.json +29 -29
- package/session.vim +4 -4
- package/setup.cfg +2 -2
- package/src/ast.pyj +7 -0
- package/src/baselib-containers.pyj +41 -4
- package/src/baselib-errors.pyj +4 -3
- package/src/baselib-internal.pyj +47 -18
- package/src/baselib-str.pyj +16 -3
- package/src/compiler.pyj +36 -36
- package/src/errors.pyj +30 -30
- package/src/lib/aes.pyj +646 -646
- package/src/lib/collections.pyj +227 -3
- package/src/lib/copy.pyj +120 -120
- package/src/lib/elementmaker.pyj +83 -83
- package/src/lib/encodings.pyj +126 -126
- 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/pprint.pyj +455 -0
- package/src/lib/random.pyj +118 -118
- package/src/lib/react.pyj +74 -74
- package/src/lib/statistics.pyj +0 -0
- package/src/lib/traceback.pyj +63 -63
- package/src/lib/uuid.pyj +77 -77
- package/src/monaco-language-service/completions.js +21 -14
- package/src/monaco-language-service/diagnostics.js +2 -2
- package/src/monaco-language-service/dts.js +58 -15
- package/src/monaco-language-service/package.json +3 -0
- package/src/output/classes.pyj +25 -2
- package/src/output/codegen.pyj +4 -1
- package/src/output/comments.pyj +45 -45
- package/src/output/exceptions.pyj +201 -201
- package/src/output/jsx.pyj +164 -164
- package/src/output/treeshake.pyj +182 -182
- package/src/output/utils.pyj +72 -72
- package/src/parse.pyj +42 -7
- package/src/string_interpolation.pyj +72 -72
- package/src/tokenizer.pyj +18 -2
- 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/baselib.pyj +23 -0
- package/test/chainmap.pyj +185 -0
- package/test/dataclasses.pyj +3 -4
- package/test/decorators.pyj +77 -77
- package/test/docstrings.pyj +39 -39
- package/test/elementmaker_test.pyj +45 -45
- package/test/enum.pyj +1 -1
- package/test/functions.pyj +151 -151
- package/test/generators.pyj +41 -41
- package/test/generic.pyj +370 -370
- 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/pprint.pyj +232 -0
- package/test/python_features.pyj +1 -1
- package/test/repl.pyj +121 -121
- package/test/scoped_flags.pyj +76 -76
- package/test/statistics.pyj +224 -0
- package/test/str.pyj +4 -4
- package/test/unit/index.js +455 -0
- package/test/unit/language-service-completions.js +2 -0
- package/test/unit/language-service-dts.js +113 -0
- package/test/unit/language-service-hover.js +455 -455
- package/test/unit/language-service.js +135 -2
- package/test/unit/web-repl.js +349 -1
- package/tools/compiler.d.ts +367 -367
- package/tools/completer.js +131 -131
- package/tools/export.js +4 -2
- 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 +141 -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/prism.css +139 -139
- package/web-repl/prism.js +113 -113
- package/web-repl/rapydscript.js +228 -226
- package/web-repl/sha1.js +25 -25
package/test/annotations.pyj
CHANGED
|
@@ -1,80 +1,80 @@
|
|
|
1
|
-
def add(a: int, b: float):
|
|
2
|
-
return a + b
|
|
3
|
-
|
|
4
|
-
assrt.ok(add.__annotations__)
|
|
5
|
-
assrt.equal(add.__annotations__['a'], int)
|
|
6
|
-
assrt.equal(add.__annotations__['b'], float)
|
|
7
|
-
assrt.equal(add.__annotations__['return'], undefined)
|
|
8
|
-
|
|
9
|
-
def sum(ls: list) -> int:
|
|
10
|
-
pass
|
|
11
|
-
|
|
12
|
-
assrt.ok(not (sum.__annotations__ == undefined))
|
|
13
|
-
assrt.deepEqual(sum.__annotations__, {
|
|
14
|
-
'ls': list,
|
|
15
|
-
'return': int
|
|
16
|
-
})
|
|
17
|
-
|
|
18
|
-
def optional(a:int=10):
|
|
19
|
-
return a
|
|
20
|
-
|
|
21
|
-
assrt.ok(not (optional.__annotations__ == undefined))
|
|
22
|
-
assrt.equal(optional.__annotations__.a, int)
|
|
23
|
-
assrt.equal(optional.__defaults__.a, 10)
|
|
24
|
-
|
|
25
|
-
def otherexpr(a:3+4) -> [1, 2]:
|
|
26
|
-
pass
|
|
27
|
-
|
|
28
|
-
assrt.ok(not (otherexpr.__annotations__ == undefined))
|
|
29
|
-
assrt.equal(otherexpr.__annotations__['a'], 7)
|
|
30
|
-
assrt.deepEqual(otherexpr.__annotations__['return'], [1, 2])
|
|
31
|
-
|
|
32
|
-
def basic(x:float):
|
|
33
|
-
pass
|
|
34
|
-
|
|
35
|
-
assrt.deepEqual(basic.__annotations__, {
|
|
36
|
-
'x': float
|
|
37
|
-
})
|
|
38
|
-
|
|
39
|
-
def kwstarargs(*args:list, **kwargs:dict) -> int:
|
|
40
|
-
pass
|
|
41
|
-
|
|
42
|
-
assrt.equal(kwstarargs.__annotations__['return'], int)
|
|
43
|
-
|
|
44
|
-
def nothing():
|
|
45
|
-
pass
|
|
46
|
-
|
|
47
|
-
assrt.ok(nothing.__annotations__ == undefined)
|
|
48
|
-
assrt.throws(def():
|
|
49
|
-
nothing.__annotations__['return']
|
|
50
|
-
)
|
|
51
|
-
|
|
52
|
-
test = def(x: int):
|
|
53
|
-
pass
|
|
54
|
-
|
|
55
|
-
assrt.deepEqual(test.__annotations__, {
|
|
56
|
-
'x': int
|
|
57
|
-
})
|
|
58
|
-
|
|
59
|
-
anonreturn = def() -> 'test':
|
|
60
|
-
pass
|
|
61
|
-
|
|
62
|
-
assrt.equal(anonreturn.__annotations__['return'], 'test')
|
|
63
|
-
|
|
64
|
-
assrt.equal(def asexpr(a: int):
|
|
65
|
-
a
|
|
66
|
-
.__annotations__['a'], int)
|
|
67
|
-
|
|
68
|
-
assrt.deepEqual(def(a: int) -> float:
|
|
69
|
-
a + 10.0
|
|
70
|
-
.__annotations__, {
|
|
71
|
-
'a': int,
|
|
72
|
-
'return': float
|
|
73
|
-
})
|
|
74
|
-
|
|
75
|
-
class A:
|
|
76
|
-
|
|
77
|
-
def f(self, a : int, b: 'x') -> float:
|
|
78
|
-
pass
|
|
79
|
-
|
|
80
|
-
assrt.deepEqual(A.prototype.f.__annotations__, {'a':int, 'b':'x', 'return': float})
|
|
1
|
+
def add(a: int, b: float):
|
|
2
|
+
return a + b
|
|
3
|
+
|
|
4
|
+
assrt.ok(add.__annotations__)
|
|
5
|
+
assrt.equal(add.__annotations__['a'], int)
|
|
6
|
+
assrt.equal(add.__annotations__['b'], float)
|
|
7
|
+
assrt.equal(add.__annotations__['return'], undefined)
|
|
8
|
+
|
|
9
|
+
def sum(ls: list) -> int:
|
|
10
|
+
pass
|
|
11
|
+
|
|
12
|
+
assrt.ok(not (sum.__annotations__ == undefined))
|
|
13
|
+
assrt.deepEqual(sum.__annotations__, {
|
|
14
|
+
'ls': list,
|
|
15
|
+
'return': int
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
def optional(a:int=10):
|
|
19
|
+
return a
|
|
20
|
+
|
|
21
|
+
assrt.ok(not (optional.__annotations__ == undefined))
|
|
22
|
+
assrt.equal(optional.__annotations__.a, int)
|
|
23
|
+
assrt.equal(optional.__defaults__.a, 10)
|
|
24
|
+
|
|
25
|
+
def otherexpr(a:3+4) -> [1, 2]:
|
|
26
|
+
pass
|
|
27
|
+
|
|
28
|
+
assrt.ok(not (otherexpr.__annotations__ == undefined))
|
|
29
|
+
assrt.equal(otherexpr.__annotations__['a'], 7)
|
|
30
|
+
assrt.deepEqual(otherexpr.__annotations__['return'], [1, 2])
|
|
31
|
+
|
|
32
|
+
def basic(x:float):
|
|
33
|
+
pass
|
|
34
|
+
|
|
35
|
+
assrt.deepEqual(basic.__annotations__, {
|
|
36
|
+
'x': float
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
def kwstarargs(*args:list, **kwargs:dict) -> int:
|
|
40
|
+
pass
|
|
41
|
+
|
|
42
|
+
assrt.equal(kwstarargs.__annotations__['return'], int)
|
|
43
|
+
|
|
44
|
+
def nothing():
|
|
45
|
+
pass
|
|
46
|
+
|
|
47
|
+
assrt.ok(nothing.__annotations__ == undefined)
|
|
48
|
+
assrt.throws(def():
|
|
49
|
+
nothing.__annotations__['return']
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
test = def(x: int):
|
|
53
|
+
pass
|
|
54
|
+
|
|
55
|
+
assrt.deepEqual(test.__annotations__, {
|
|
56
|
+
'x': int
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
anonreturn = def() -> 'test':
|
|
60
|
+
pass
|
|
61
|
+
|
|
62
|
+
assrt.equal(anonreturn.__annotations__['return'], 'test')
|
|
63
|
+
|
|
64
|
+
assrt.equal(def asexpr(a: int):
|
|
65
|
+
a
|
|
66
|
+
.__annotations__['a'], int)
|
|
67
|
+
|
|
68
|
+
assrt.deepEqual(def(a: int) -> float:
|
|
69
|
+
a + 10.0
|
|
70
|
+
.__annotations__, {
|
|
71
|
+
'a': int,
|
|
72
|
+
'return': float
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
class A:
|
|
76
|
+
|
|
77
|
+
def f(self, a : int, b: 'x') -> float:
|
|
78
|
+
pass
|
|
79
|
+
|
|
80
|
+
assrt.deepEqual(A.prototype.f.__annotations__, {'a':int, 'b':'x', 'return': float})
|
package/test/baselib.pyj
CHANGED
|
@@ -159,6 +159,29 @@ a.sort()
|
|
|
159
159
|
assrt.deepEqual(a, [1,2,3,4])
|
|
160
160
|
a.sort(reverse=True)
|
|
161
161
|
assrt.deepEqual(a, [4,3,2,1])
|
|
162
|
+
|
|
163
|
+
# sort: a positional two-argument function is treated as a comparator
|
|
164
|
+
assrt.deepEqual(sorted([3, 1, 2, 10], def(x, y): return x - y;), [1, 2, 3, 10])
|
|
165
|
+
assrt.deepEqual(sorted([3, 1, 2, 10], def(x, y): return y - x;), [10, 3, 2, 1])
|
|
166
|
+
sort_cmp = [5, 2, 8, 1]
|
|
167
|
+
sort_cmp.sort(def(x, y): return x - y;)
|
|
168
|
+
assrt.deepEqual(sort_cmp, [1, 2, 5, 8])
|
|
169
|
+
# a one-argument function is still a key function
|
|
170
|
+
assrt.deepEqual(sorted([3, 1, 2], key=def(x): return -x;), [3, 2, 1])
|
|
171
|
+
# comparator path keeps ties in their original order (stable)
|
|
172
|
+
assrt.deepEqual(sorted([[1, 'a'], [1, 'b'], [0, 'c']], def(p, q): return p[0] - q[0];),
|
|
173
|
+
[[0, 'c'], [1, 'a'], [1, 'b']])
|
|
174
|
+
|
|
175
|
+
# sort: custom objects are ordered via their __lt__ method
|
|
176
|
+
class SortOrd:
|
|
177
|
+
def __init__(self, v):
|
|
178
|
+
self.v = v
|
|
179
|
+
def __lt__(self, other):
|
|
180
|
+
return self.v < other.v
|
|
181
|
+
ord_asc = sorted([SortOrd(3), SortOrd(1), SortOrd(2)])
|
|
182
|
+
assrt.deepEqual([ord_asc[0].v, ord_asc[1].v, ord_asc[2].v], [1, 2, 3])
|
|
183
|
+
ord_desc = sorted([SortOrd(3), SortOrd(1), SortOrd(2)], reverse=True)
|
|
184
|
+
assrt.deepEqual([ord_desc[0].v, ord_desc[1].v, ord_desc[2].v], [3, 2, 1])
|
|
162
185
|
assrt.deepEqual(a, a.slice())
|
|
163
186
|
assrt.ok(a is not a.slice())
|
|
164
187
|
assrt.ok(a.slice().extend is not undefined)
|
|
@@ -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')
|
package/test/dataclasses.pyj
CHANGED
|
@@ -76,7 +76,7 @@ class _Hidden:
|
|
|
76
76
|
secret: str = field('s3cr3t', repr=False)
|
|
77
77
|
|
|
78
78
|
h = _Hidden("visible")
|
|
79
|
-
ae(repr(h),
|
|
79
|
+
ae(repr(h), "_Hidden(public='visible')")
|
|
80
80
|
ae(h.secret, 's3cr3t')
|
|
81
81
|
|
|
82
82
|
# ── 6. field() init=False ─────────────────────────────────────────────────────
|
|
@@ -209,11 +209,10 @@ ae(ch2.y, 0)
|
|
|
209
209
|
ae(ch2.z, 'default')
|
|
210
210
|
|
|
211
211
|
# repr shows all fields including inherited
|
|
212
|
-
# (RapydScript repr() uses double quotes for strings, like JavaScript)
|
|
213
212
|
r = repr(ch2)
|
|
214
213
|
ok('x=10' in r)
|
|
215
214
|
ok('y=0' in r)
|
|
216
|
-
ok(
|
|
215
|
+
ok("z='default'" in r)
|
|
217
216
|
|
|
218
217
|
# ── 15. MISSING sentinel ──────────────────────────────────────────────────────
|
|
219
218
|
|
|
@@ -240,7 +239,7 @@ class _Explicit:
|
|
|
240
239
|
|
|
241
240
|
ex = _Explicit()
|
|
242
241
|
ae(ex.name, 'x')
|
|
243
|
-
ae(repr(ex),
|
|
242
|
+
ae(repr(ex), "_Explicit(name='x')")
|
|
244
243
|
|
|
245
244
|
# ── 18. Nested list field with asdict ────────────────────────────────────────
|
|
246
245
|
|
package/test/decorators.pyj
CHANGED
|
@@ -1,77 +1,77 @@
|
|
|
1
|
-
# vim:fileencoding=utf-8
|
|
2
|
-
# License: BSD Copyright: 2015, Kovid Goyal <kovid at kovidgoyal.net>
|
|
3
|
-
|
|
4
|
-
def double(f):
|
|
5
|
-
return def (x):
|
|
6
|
-
return 2 * f(x)
|
|
7
|
-
|
|
8
|
-
def triple(f):
|
|
9
|
-
return def(x):
|
|
10
|
-
return 3 * f(x)
|
|
11
|
-
|
|
12
|
-
@double
|
|
13
|
-
def half(x):
|
|
14
|
-
return x // 2
|
|
15
|
-
|
|
16
|
-
@double
|
|
17
|
-
def f1(x):
|
|
18
|
-
return x
|
|
19
|
-
|
|
20
|
-
@double
|
|
21
|
-
@triple
|
|
22
|
-
def f2(x):
|
|
23
|
-
return x
|
|
24
|
-
|
|
25
|
-
def append_one(f):
|
|
26
|
-
return def(x):
|
|
27
|
-
ans = f(x)
|
|
28
|
-
ans.push(1)
|
|
29
|
-
return ans
|
|
30
|
-
|
|
31
|
-
def append_two(f):
|
|
32
|
-
return def(x):
|
|
33
|
-
ans = f(x)
|
|
34
|
-
ans.push(2)
|
|
35
|
-
return ans
|
|
36
|
-
|
|
37
|
-
@append_two
|
|
38
|
-
@append_one
|
|
39
|
-
def f3():
|
|
40
|
-
return []
|
|
41
|
-
|
|
42
|
-
o = {'double':double}
|
|
43
|
-
|
|
44
|
-
@o.double
|
|
45
|
-
def f4():
|
|
46
|
-
return 1
|
|
47
|
-
|
|
48
|
-
assrt.equal(2, half(2))
|
|
49
|
-
assrt.equal(4, f1(2))
|
|
50
|
-
assrt.equal(12, f2(2))
|
|
51
|
-
assrt.equal(2, f4())
|
|
52
|
-
assrt.deepEqual([1, 2], f3())
|
|
53
|
-
|
|
54
|
-
def multiply(amt):
|
|
55
|
-
|
|
56
|
-
def wrapper(f):
|
|
57
|
-
return def ():
|
|
58
|
-
return amt * f()
|
|
59
|
-
|
|
60
|
-
return wrapper
|
|
61
|
-
|
|
62
|
-
@multiply(2)
|
|
63
|
-
def two():
|
|
64
|
-
return 1
|
|
65
|
-
|
|
66
|
-
@multiply(3)
|
|
67
|
-
def three():
|
|
68
|
-
return 1
|
|
69
|
-
|
|
70
|
-
@multiply(2)
|
|
71
|
-
@multiply(2)
|
|
72
|
-
def four():
|
|
73
|
-
return 1
|
|
74
|
-
|
|
75
|
-
assrt.equal(2, two())
|
|
76
|
-
assrt.equal(3, three())
|
|
77
|
-
assrt.equal(4, four())
|
|
1
|
+
# vim:fileencoding=utf-8
|
|
2
|
+
# License: BSD Copyright: 2015, Kovid Goyal <kovid at kovidgoyal.net>
|
|
3
|
+
|
|
4
|
+
def double(f):
|
|
5
|
+
return def (x):
|
|
6
|
+
return 2 * f(x)
|
|
7
|
+
|
|
8
|
+
def triple(f):
|
|
9
|
+
return def(x):
|
|
10
|
+
return 3 * f(x)
|
|
11
|
+
|
|
12
|
+
@double
|
|
13
|
+
def half(x):
|
|
14
|
+
return x // 2
|
|
15
|
+
|
|
16
|
+
@double
|
|
17
|
+
def f1(x):
|
|
18
|
+
return x
|
|
19
|
+
|
|
20
|
+
@double
|
|
21
|
+
@triple
|
|
22
|
+
def f2(x):
|
|
23
|
+
return x
|
|
24
|
+
|
|
25
|
+
def append_one(f):
|
|
26
|
+
return def(x):
|
|
27
|
+
ans = f(x)
|
|
28
|
+
ans.push(1)
|
|
29
|
+
return ans
|
|
30
|
+
|
|
31
|
+
def append_two(f):
|
|
32
|
+
return def(x):
|
|
33
|
+
ans = f(x)
|
|
34
|
+
ans.push(2)
|
|
35
|
+
return ans
|
|
36
|
+
|
|
37
|
+
@append_two
|
|
38
|
+
@append_one
|
|
39
|
+
def f3():
|
|
40
|
+
return []
|
|
41
|
+
|
|
42
|
+
o = {'double':double}
|
|
43
|
+
|
|
44
|
+
@o.double
|
|
45
|
+
def f4():
|
|
46
|
+
return 1
|
|
47
|
+
|
|
48
|
+
assrt.equal(2, half(2))
|
|
49
|
+
assrt.equal(4, f1(2))
|
|
50
|
+
assrt.equal(12, f2(2))
|
|
51
|
+
assrt.equal(2, f4())
|
|
52
|
+
assrt.deepEqual([1, 2], f3())
|
|
53
|
+
|
|
54
|
+
def multiply(amt):
|
|
55
|
+
|
|
56
|
+
def wrapper(f):
|
|
57
|
+
return def ():
|
|
58
|
+
return amt * f()
|
|
59
|
+
|
|
60
|
+
return wrapper
|
|
61
|
+
|
|
62
|
+
@multiply(2)
|
|
63
|
+
def two():
|
|
64
|
+
return 1
|
|
65
|
+
|
|
66
|
+
@multiply(3)
|
|
67
|
+
def three():
|
|
68
|
+
return 1
|
|
69
|
+
|
|
70
|
+
@multiply(2)
|
|
71
|
+
@multiply(2)
|
|
72
|
+
def four():
|
|
73
|
+
return 1
|
|
74
|
+
|
|
75
|
+
assrt.equal(2, two())
|
|
76
|
+
assrt.equal(3, three())
|
|
77
|
+
assrt.equal(4, four())
|
package/test/docstrings.pyj
CHANGED
|
@@ -1,39 +1,39 @@
|
|
|
1
|
-
# vim:fileencoding=utf-8
|
|
2
|
-
# License: BSD Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
|
|
3
|
-
# globals: ρσ_module_doc__
|
|
4
|
-
|
|
5
|
-
import _import_one
|
|
6
|
-
|
|
7
|
-
def f():
|
|
8
|
-
" A basic docstring "
|
|
9
|
-
pass
|
|
10
|
-
|
|
11
|
-
assrt.equal(f.__doc__, 'A basic docstring')
|
|
12
|
-
assrt.equal(_import_one.__doc__, 'Module level ds1\n\nModule level ds2\nline2\n\nModule level ds 3')
|
|
13
|
-
|
|
14
|
-
def g():
|
|
15
|
-
'''
|
|
16
|
-
A more complex docstring:
|
|
17
|
-
xxx
|
|
18
|
-
yyyy
|
|
19
|
-
|
|
20
|
-
the end
|
|
21
|
-
'''
|
|
22
|
-
pass
|
|
23
|
-
|
|
24
|
-
assrt.equal(g.__doc__, 'A more complex docstring:\n xxx\n yyyy\n\nthe end')
|
|
25
|
-
|
|
26
|
-
class D:
|
|
27
|
-
' Docstring for a class '
|
|
28
|
-
|
|
29
|
-
def method(self):
|
|
30
|
-
'ds for a method'
|
|
31
|
-
pass
|
|
32
|
-
|
|
33
|
-
assrt.equal(D().__doc__, 'Docstring for a class')
|
|
34
|
-
assrt.equal(D().method.__doc__, 'ds for a method')
|
|
35
|
-
|
|
36
|
-
x = def():
|
|
37
|
-
'xxx'
|
|
38
|
-
|
|
39
|
-
assrt.equal(x.__doc__, 'xxx')
|
|
1
|
+
# vim:fileencoding=utf-8
|
|
2
|
+
# License: BSD Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
|
|
3
|
+
# globals: ρσ_module_doc__
|
|
4
|
+
|
|
5
|
+
import _import_one
|
|
6
|
+
|
|
7
|
+
def f():
|
|
8
|
+
" A basic docstring "
|
|
9
|
+
pass
|
|
10
|
+
|
|
11
|
+
assrt.equal(f.__doc__, 'A basic docstring')
|
|
12
|
+
assrt.equal(_import_one.__doc__, 'Module level ds1\n\nModule level ds2\nline2\n\nModule level ds 3')
|
|
13
|
+
|
|
14
|
+
def g():
|
|
15
|
+
'''
|
|
16
|
+
A more complex docstring:
|
|
17
|
+
xxx
|
|
18
|
+
yyyy
|
|
19
|
+
|
|
20
|
+
the end
|
|
21
|
+
'''
|
|
22
|
+
pass
|
|
23
|
+
|
|
24
|
+
assrt.equal(g.__doc__, 'A more complex docstring:\n xxx\n yyyy\n\nthe end')
|
|
25
|
+
|
|
26
|
+
class D:
|
|
27
|
+
' Docstring for a class '
|
|
28
|
+
|
|
29
|
+
def method(self):
|
|
30
|
+
'ds for a method'
|
|
31
|
+
pass
|
|
32
|
+
|
|
33
|
+
assrt.equal(D().__doc__, 'Docstring for a class')
|
|
34
|
+
assrt.equal(D().method.__doc__, 'ds for a method')
|
|
35
|
+
|
|
36
|
+
x = def():
|
|
37
|
+
'xxx'
|
|
38
|
+
|
|
39
|
+
assrt.equal(x.__doc__, 'xxx')
|