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.
Files changed (88) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/PYTHON_GAPS.md +352 -0
  3. package/README.md +176 -32
  4. package/TODO.md +1 -128
  5. package/bin/rapydscript +70 -70
  6. package/language-service/index.js +242 -11
  7. package/memory/project_string_impl.md +43 -0
  8. package/package.json +1 -1
  9. package/release/baselib-plain-pretty.js +248 -38
  10. package/release/baselib-plain-ugly.js +8 -8
  11. package/release/compiler.js +778 -277
  12. package/release/signatures.json +30 -30
  13. package/src/ast.pyj +10 -1
  14. package/src/baselib-builtins.pyj +56 -2
  15. package/src/baselib-containers.pyj +25 -1
  16. package/src/baselib-errors.pyj +7 -3
  17. package/src/baselib-internal.pyj +51 -6
  18. package/src/baselib-str.pyj +18 -5
  19. package/src/lib/asyncio.pyj +534 -0
  20. package/src/lib/base64.pyj +399 -0
  21. package/src/lib/bisect.pyj +73 -0
  22. package/src/lib/collections.pyj +228 -4
  23. package/src/lib/csv.pyj +494 -0
  24. package/src/lib/heapq.pyj +98 -0
  25. package/src/lib/html.pyj +382 -0
  26. package/src/lib/http/__init__.pyj +98 -0
  27. package/src/lib/http/client.pyj +304 -0
  28. package/src/lib/http/cookies.pyj +236 -0
  29. package/src/lib/logging.pyj +672 -0
  30. package/src/lib/pprint.pyj +455 -0
  31. package/src/lib/pythonize.pyj +20 -20
  32. package/src/lib/statistics.pyj +0 -0
  33. package/src/lib/string.pyj +357 -0
  34. package/src/lib/textwrap.pyj +329 -0
  35. package/src/lib/urllib/__init__.pyj +14 -0
  36. package/src/lib/urllib/error.pyj +66 -0
  37. package/src/lib/urllib/parse.pyj +475 -0
  38. package/src/lib/urllib/request.pyj +86 -0
  39. package/src/monaco-language-service/analyzer.js +5 -2
  40. package/src/monaco-language-service/completions.js +26 -0
  41. package/src/monaco-language-service/diagnostics.js +203 -4
  42. package/src/monaco-language-service/scope.js +1 -0
  43. package/src/output/codegen.pyj +4 -1
  44. package/src/output/functions.pyj +152 -6
  45. package/src/output/loops.pyj +17 -2
  46. package/src/output/modules.pyj +1 -1
  47. package/src/output/operators.pyj +15 -0
  48. package/src/output/stream.pyj +0 -1
  49. package/src/parse.pyj +108 -24
  50. package/src/tokenizer.pyj +19 -3
  51. package/test/async_generators.pyj +144 -0
  52. package/test/asyncio.pyj +307 -0
  53. package/test/base64.pyj +202 -0
  54. package/test/baselib.pyj +23 -0
  55. package/test/bisect.pyj +178 -0
  56. package/test/chainmap.pyj +185 -0
  57. package/test/csv.pyj +405 -0
  58. package/test/float_special.pyj +64 -0
  59. package/test/heapq.pyj +174 -0
  60. package/test/html.pyj +212 -0
  61. package/test/http.pyj +259 -0
  62. package/test/imports.pyj +79 -72
  63. package/test/logging.pyj +356 -0
  64. package/test/long.pyj +130 -0
  65. package/test/parenthesized_with.pyj +141 -0
  66. package/test/pprint.pyj +232 -0
  67. package/test/python_compat.pyj +3 -5
  68. package/test/python_modulo.pyj +76 -0
  69. package/test/python_modulo_off.pyj +21 -0
  70. package/test/statistics.pyj +224 -0
  71. package/test/str.pyj +14 -0
  72. package/test/string.pyj +245 -0
  73. package/test/textwrap.pyj +172 -0
  74. package/test/type_display.pyj +48 -0
  75. package/test/type_enforcement.pyj +164 -0
  76. package/test/unit/index.js +94 -6
  77. package/test/unit/language-service-completions.js +121 -0
  78. package/test/unit/language-service-scope.js +32 -0
  79. package/test/unit/language-service.js +190 -5
  80. package/test/unit/run-language-service.js +17 -3
  81. package/test/unit/web-repl.js +2401 -13
  82. package/test/urllib.pyj +193 -0
  83. package/tools/compile.js +1 -1
  84. package/tools/embedded_compiler.js +7 -7
  85. package/tools/export.js +4 -2
  86. package/web-repl/main.js +1 -1
  87. package/web-repl/rapydscript.js +7 -5
  88. package/test/omit_function_metadata.pyj +0 -20
@@ -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')