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
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# globals: assrt
|
|
2
|
+
# vim:fileencoding=utf-8
|
|
3
|
+
#
|
|
4
|
+
# parenthesized_with.pyj
|
|
5
|
+
# Tests for Python 3.10+ parenthesized `with` statement.
|
|
6
|
+
|
|
7
|
+
ae = assrt.equal
|
|
8
|
+
ok = assrt.ok
|
|
9
|
+
|
|
10
|
+
# ── Helper context manager ────────────────────────────────────────────────────
|
|
11
|
+
|
|
12
|
+
class _CM:
|
|
13
|
+
def __init__(self, name, log):
|
|
14
|
+
self.name = name
|
|
15
|
+
self.log = log
|
|
16
|
+
|
|
17
|
+
def __enter__(self):
|
|
18
|
+
self.log.push('enter:' + self.name)
|
|
19
|
+
return self
|
|
20
|
+
|
|
21
|
+
def __exit__(self, *args):
|
|
22
|
+
self.log.push('exit:' + self.name)
|
|
23
|
+
return False
|
|
24
|
+
|
|
25
|
+
# ── 1. Single clause, alias inside parens ─────────────────────────────────────
|
|
26
|
+
|
|
27
|
+
_log1 = []
|
|
28
|
+
with (_CM('a', _log1) as cm):
|
|
29
|
+
_log1.push('body')
|
|
30
|
+
ae(_log1[0], 'enter:a')
|
|
31
|
+
ae(_log1[1], 'body')
|
|
32
|
+
ae(_log1[2], 'exit:a')
|
|
33
|
+
|
|
34
|
+
# ── 2. Single clause, no alias ────────────────────────────────────────────────
|
|
35
|
+
|
|
36
|
+
_log2 = []
|
|
37
|
+
|
|
38
|
+
class _SimpleCM:
|
|
39
|
+
def __init__(self, log):
|
|
40
|
+
self.log = log
|
|
41
|
+
def __enter__(self):
|
|
42
|
+
self.log.push('entered')
|
|
43
|
+
return self
|
|
44
|
+
def __exit__(self):
|
|
45
|
+
self.log.push('exited')
|
|
46
|
+
|
|
47
|
+
with (_SimpleCM(_log2)):
|
|
48
|
+
_log2.push('body')
|
|
49
|
+
ae(_log2[0], 'entered')
|
|
50
|
+
ae(_log2[1], 'body')
|
|
51
|
+
ae(_log2[2], 'exited')
|
|
52
|
+
|
|
53
|
+
# ── 3. Multi-clause, LIFO exit order ──────────────────────────────────────────
|
|
54
|
+
|
|
55
|
+
_log3 = []
|
|
56
|
+
with (_CM('a', _log3) as a, _CM('b', _log3) as b):
|
|
57
|
+
_log3.push('body')
|
|
58
|
+
ae(_log3[0], 'enter:a')
|
|
59
|
+
ae(_log3[1], 'enter:b')
|
|
60
|
+
ae(_log3[2], 'body')
|
|
61
|
+
ae(_log3[3], 'exit:b') # LIFO: b exits before a
|
|
62
|
+
ae(_log3[4], 'exit:a')
|
|
63
|
+
|
|
64
|
+
# ── 4. Trailing comma ─────────────────────────────────────────────────────────
|
|
65
|
+
|
|
66
|
+
_log4 = []
|
|
67
|
+
with (_CM('x', _log4) as x,):
|
|
68
|
+
_log4.push('body')
|
|
69
|
+
ae(_log4[0], 'enter:x')
|
|
70
|
+
ae(_log4[1], 'body')
|
|
71
|
+
ae(_log4[2], 'exit:x')
|
|
72
|
+
|
|
73
|
+
# ── 5. Multi-line form ────────────────────────────────────────────────────────
|
|
74
|
+
|
|
75
|
+
_log5 = []
|
|
76
|
+
with (
|
|
77
|
+
_CM('p', _log5) as p,
|
|
78
|
+
_CM('q', _log5) as q,
|
|
79
|
+
):
|
|
80
|
+
_log5.push('body')
|
|
81
|
+
ae(_log5[0], 'enter:p')
|
|
82
|
+
ae(_log5[1], 'enter:q')
|
|
83
|
+
ae(_log5[2], 'body')
|
|
84
|
+
ae(_log5[3], 'exit:q')
|
|
85
|
+
ae(_log5[4], 'exit:p')
|
|
86
|
+
|
|
87
|
+
# ── 6. __enter__ return value assigned to alias ───────────────────────────────
|
|
88
|
+
|
|
89
|
+
class _ValCM:
|
|
90
|
+
def __init__(self, val):
|
|
91
|
+
self.val = val
|
|
92
|
+
def __enter__(self):
|
|
93
|
+
return self.val
|
|
94
|
+
def __exit__(self):
|
|
95
|
+
pass
|
|
96
|
+
|
|
97
|
+
with (_ValCM(99) as v):
|
|
98
|
+
ae(v, 99)
|
|
99
|
+
|
|
100
|
+
# ── 7. Exception suppression via __exit__ ─────────────────────────────────────
|
|
101
|
+
|
|
102
|
+
class _SuppressCM:
|
|
103
|
+
def __enter__(self):
|
|
104
|
+
return self
|
|
105
|
+
def __exit__(self, *args):
|
|
106
|
+
return True # suppress any exception
|
|
107
|
+
|
|
108
|
+
_raised = False
|
|
109
|
+
with (_SuppressCM()):
|
|
110
|
+
raise Error('suppressed')
|
|
111
|
+
_raised = True
|
|
112
|
+
ok(_raised)
|
|
113
|
+
|
|
114
|
+
# ── 8. Exception propagation (unsuppressed) ──────────────────────────────────
|
|
115
|
+
|
|
116
|
+
_caught = False
|
|
117
|
+
try:
|
|
118
|
+
with (_CM('err', []) as _ignored):
|
|
119
|
+
raise Error('propagated')
|
|
120
|
+
except Exception as _e:
|
|
121
|
+
_caught = True
|
|
122
|
+
ok(_caught)
|
|
123
|
+
|
|
124
|
+
# ── 9. Non-parenthesized form still works (regression) ───────────────────────
|
|
125
|
+
|
|
126
|
+
_log9 = []
|
|
127
|
+
with _CM('r', _log9) as r, _CM('s', _log9) as s:
|
|
128
|
+
_log9.push('body')
|
|
129
|
+
ae(_log9[0], 'enter:r')
|
|
130
|
+
ae(_log9[3], 'exit:s')
|
|
131
|
+
ae(_log9[4], 'exit:r')
|
|
132
|
+
|
|
133
|
+
# ── 10. Parenthesized expression (not parenthesized-with) still works ─────────
|
|
134
|
+
|
|
135
|
+
_log10 = []
|
|
136
|
+
_cm10 = _CM('t', _log10)
|
|
137
|
+
with (_cm10) as t:
|
|
138
|
+
_log10.push('body')
|
|
139
|
+
ae(_log10[0], 'enter:t')
|
|
140
|
+
ae(_log10[1], 'body')
|
|
141
|
+
ae(_log10[2], 'exit:t')
|
package/test/python_compat.pyj
CHANGED
|
@@ -235,7 +235,7 @@ strings()
|
|
|
235
235
|
ae(' hello '.strip(), 'hello')
|
|
236
236
|
ae('hello world'.upper(), 'HELLO WORLD')
|
|
237
237
|
|
|
238
|
-
# ── 15. strings()
|
|
238
|
+
# ── 15. strings() patches replace(); split() defaults to ' ' ──────────────────
|
|
239
239
|
# (strings() is active from section 14 above)
|
|
240
240
|
# Python str.split() with no args: splits on any whitespace, strips leading/trailing.
|
|
241
241
|
# RapydScript .split() with no args: transpiles to .split(" ") — splits on single space.
|
|
@@ -248,11 +248,9 @@ ade(str.split('a b c'), ['a', 'b', 'c'])
|
|
|
248
248
|
ade('a b'.split(), ['a', '', 'b']) # double space → empty token between
|
|
249
249
|
ade('a b'.split(' '), ['a', 'b']) # explicit ' ' separator still works
|
|
250
250
|
|
|
251
|
-
#
|
|
252
|
-
# Python replaces ALL occurrences by default.
|
|
253
|
-
# JS .replace() with a string pattern only replaces the FIRST occurrence.
|
|
251
|
+
# str.replace() and String.prototype.replace() both use Python semantics (replace all).
|
|
254
252
|
ae(str.replace('aaa', 'a', 'b'), 'bbb') # Python: replaces all
|
|
255
|
-
ae('aaa'.replace('a', 'b'), '
|
|
253
|
+
ae('aaa'.replace('a', 'b'), 'bbb') # also replaces all (pythonized)
|
|
256
254
|
|
|
257
255
|
# ── 16. Method binding — not automatic ──────────────────────────────────────
|
|
258
256
|
# Python: bound methods carry a reference to self.
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# globals: assrt
|
|
2
|
+
# vim:fileencoding=utf-8
|
|
3
|
+
#
|
|
4
|
+
# python_modulo.pyj
|
|
5
|
+
# Tests for Python-style modulo: result takes the sign of the divisor.
|
|
6
|
+
# python_modulo defaults to True; no __python__ import needed.
|
|
7
|
+
|
|
8
|
+
ae = assrt.equal
|
|
9
|
+
ok = assrt.ok
|
|
10
|
+
|
|
11
|
+
# ── Positive operands ────────────────────────────────────────────────────────
|
|
12
|
+
ae(7 % 3, 1)
|
|
13
|
+
ae(0 % 5, 0)
|
|
14
|
+
ae(6 % 3, 0)
|
|
15
|
+
|
|
16
|
+
# ── Negative dividend ────────────────────────────────────────────────────────
|
|
17
|
+
ae(-7 % 3, 2)
|
|
18
|
+
ae(-1 % 3, 2)
|
|
19
|
+
ae(-6 % 3, 0)
|
|
20
|
+
|
|
21
|
+
# ── Negative divisor ─────────────────────────────────────────────────────────
|
|
22
|
+
ae(7 % -3, -2)
|
|
23
|
+
ae(1 % -3, -2)
|
|
24
|
+
ae(6 % -3, 0)
|
|
25
|
+
|
|
26
|
+
# ── Both negative ────────────────────────────────────────────────────────────
|
|
27
|
+
ae(-7 % -3, -1)
|
|
28
|
+
ae(-1 % -3, -1)
|
|
29
|
+
ae(-6 % -3, 0)
|
|
30
|
+
|
|
31
|
+
# ── Floats ───────────────────────────────────────────────────────────────────
|
|
32
|
+
ae(-7.5 % 2, 0.5)
|
|
33
|
+
ae(7.5 % -2, -0.5)
|
|
34
|
+
ae(2.5 % 1, 0.5)
|
|
35
|
+
|
|
36
|
+
# ── Booleans (treated as numbers) ────────────────────────────────────────────
|
|
37
|
+
ae(5 % True, 0)
|
|
38
|
+
ae(False % 3, 0)
|
|
39
|
+
|
|
40
|
+
# ── Augmented `%=` ───────────────────────────────────────────────────────────
|
|
41
|
+
x = -7
|
|
42
|
+
x %= 3
|
|
43
|
+
ae(x, 2)
|
|
44
|
+
|
|
45
|
+
y = 7
|
|
46
|
+
y %= -3
|
|
47
|
+
ae(y, -2)
|
|
48
|
+
|
|
49
|
+
z = -7
|
|
50
|
+
z %= -3
|
|
51
|
+
ae(z, -1)
|
|
52
|
+
|
|
53
|
+
# ── Inside expressions ───────────────────────────────────────────────────────
|
|
54
|
+
ae((-7 % 3) + 10, 12)
|
|
55
|
+
ae(((-10) % 3) * 2, 4)
|
|
56
|
+
|
|
57
|
+
# ── Variables (not just literals) ────────────────────────────────────────────
|
|
58
|
+
a = -7
|
|
59
|
+
b = 3
|
|
60
|
+
ae(a % b, 2)
|
|
61
|
+
|
|
62
|
+
# ── BigInt (Python semantics already worked; regression guard) ───────────────
|
|
63
|
+
ae(BigInt(-7) % BigInt(3), BigInt(2))
|
|
64
|
+
ae(BigInt(7) % BigInt(-3), BigInt(-2))
|
|
65
|
+
|
|
66
|
+
# ── Custom __mod__ wins over numeric path ────────────────────────────────────
|
|
67
|
+
# python_modulo routes through ρσ_op_mod_ns which dispatches __mod__/__rmod__
|
|
68
|
+
# even without overload_operators.
|
|
69
|
+
class Mod:
|
|
70
|
+
def __init__(self, v):
|
|
71
|
+
self.v = v
|
|
72
|
+
def __mod__(self, other):
|
|
73
|
+
return 'mod-' + self.v + '-' + other
|
|
74
|
+
|
|
75
|
+
m = Mod('a')
|
|
76
|
+
ae(m % 'b', 'mod-a-b')
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# globals: assrt
|
|
2
|
+
# vim:fileencoding=utf-8
|
|
3
|
+
#
|
|
4
|
+
# python_modulo_off.pyj
|
|
5
|
+
# Tests for opting out of Python-style modulo via no_python_modulo.
|
|
6
|
+
# With the flag off, `%` emits raw JS modulo (sign of dividend).
|
|
7
|
+
|
|
8
|
+
from __python__ import no_python_modulo
|
|
9
|
+
|
|
10
|
+
ae = assrt.equal
|
|
11
|
+
|
|
12
|
+
# JS modulo: result takes the sign of the dividend.
|
|
13
|
+
ae(-7 % 3, -1) # Python would give 2
|
|
14
|
+
ae(7 % -3, 1) # Python would give -2
|
|
15
|
+
ae(-7 % -3, -1) # same as Python here
|
|
16
|
+
ae(7 % 3, 1) # positive case identical
|
|
17
|
+
|
|
18
|
+
# Augmented `%=` follows the same flag.
|
|
19
|
+
x = -7
|
|
20
|
+
x %= 3
|
|
21
|
+
ae(x, -1) # Python would give 2
|
package/test/repl.pyj
CHANGED
|
@@ -1,121 +1,121 @@
|
|
|
1
|
-
# globals: compiler_dir
|
|
2
|
-
stdout = []
|
|
3
|
-
def clear():
|
|
4
|
-
stdout.length = 0
|
|
5
|
-
|
|
6
|
-
class FakeConsole:
|
|
7
|
-
|
|
8
|
-
def log(self):
|
|
9
|
-
Array.prototype.slice.call(arguments).forEach(def (arg):
|
|
10
|
-
stdout.push((arg or '').toString())
|
|
11
|
-
)
|
|
12
|
-
stdout.push('\n')
|
|
13
|
-
|
|
14
|
-
def error(self):
|
|
15
|
-
Array.prototype.slice.call(arguments).forEach(def (arg):
|
|
16
|
-
stdout.push((arg or '').toString())
|
|
17
|
-
)
|
|
18
|
-
stdout.push('\n')
|
|
19
|
-
|
|
20
|
-
class FakeReadline:
|
|
21
|
-
|
|
22
|
-
def __init__(self):
|
|
23
|
-
self.listeners = {}
|
|
24
|
-
self._prompt = ''
|
|
25
|
-
|
|
26
|
-
def setPrompt(self, prompt):
|
|
27
|
-
self._prompt = prompt
|
|
28
|
-
|
|
29
|
-
def write(self, data):
|
|
30
|
-
stdout.push(data)
|
|
31
|
-
|
|
32
|
-
def clearLine(self):
|
|
33
|
-
pass
|
|
34
|
-
|
|
35
|
-
def on(self, event, callback):
|
|
36
|
-
self.listeners[event] = callback
|
|
37
|
-
return self
|
|
38
|
-
|
|
39
|
-
def prompt(self):
|
|
40
|
-
stdout.push(self._prompt)
|
|
41
|
-
|
|
42
|
-
def send_line(self, text):
|
|
43
|
-
self.listeners['line'](text)
|
|
44
|
-
|
|
45
|
-
repl = require('./repl')
|
|
46
|
-
rl = FakeReadline()
|
|
47
|
-
|
|
48
|
-
send_line = rl.send_line.bind(rl)
|
|
49
|
-
|
|
50
|
-
def send_text(text):
|
|
51
|
-
for line in text.split('\n'):
|
|
52
|
-
send_line(line)
|
|
53
|
-
|
|
54
|
-
def check(text, output):
|
|
55
|
-
send_text(text)
|
|
56
|
-
eq(output, stdout[0])
|
|
57
|
-
clear()
|
|
58
|
-
|
|
59
|
-
def check_in(text, output):
|
|
60
|
-
send_text(text)
|
|
61
|
-
assrt.ok(output in stdout, output + ' not in ' + stdout)
|
|
62
|
-
clear()
|
|
63
|
-
|
|
64
|
-
def check_not_in(text, output):
|
|
65
|
-
send_text(text)
|
|
66
|
-
assrt.ok(output not in stdout)
|
|
67
|
-
clear()
|
|
68
|
-
|
|
69
|
-
readline = {
|
|
70
|
-
'createInterface': def(options):
|
|
71
|
-
rl.completer = options.completer
|
|
72
|
-
return rl
|
|
73
|
-
}
|
|
74
|
-
repl({'lib_path':compiler_dir, 'console':FakeConsole(), 'readline':readline, 'terminal':False, 'show_js':False, 'histfile':False})
|
|
75
|
-
eq = assrt.equal
|
|
76
|
-
eq('>>> ', stdout[-1])
|
|
77
|
-
clear()
|
|
78
|
-
check('1', '1')
|
|
79
|
-
check_in('if 1:\n 2\n \n ', '2')
|
|
80
|
-
check_not_in('if 1:\n 2\n ', '2')
|
|
81
|
-
check_in('1 +\n1\n\n', '2')
|
|
82
|
-
check('max(1, 2)', '2')
|
|
83
|
-
send_text(
|
|
84
|
-
'''
|
|
85
|
-
class A:
|
|
86
|
-
|
|
87
|
-
def __init__(self, a):
|
|
88
|
-
self. a = a
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
''')
|
|
92
|
-
clear()
|
|
93
|
-
check_in('b = A(1)\nb.a', '1')
|
|
94
|
-
check_in('c = A(2)\nc.a', '2')
|
|
95
|
-
send_text('from __python__ import dict_literals\nd={1:1}')
|
|
96
|
-
check_in('isinstance(d, dict)', 'true')
|
|
97
|
-
send_text('from __python__ import no_dict_literals\nd={1:1}')
|
|
98
|
-
check_in('isinstance(d, dict)', 'false')
|
|
99
|
-
# Test completions
|
|
100
|
-
def completions(line):
|
|
101
|
-
return rl.completer(line)[0]
|
|
102
|
-
|
|
103
|
-
def check_completions():
|
|
104
|
-
items = completions(arguments[0])
|
|
105
|
-
for x in Array.prototype.slice.call(arguments, 1):
|
|
106
|
-
assrt.ok(items and x in items, x + ' not in completions for: ' + arguments[0])
|
|
107
|
-
|
|
108
|
-
check_completions('', 'return', 'A')
|
|
109
|
-
check_completions('Array.', 'isArray', 'apply')
|
|
110
|
-
send_text('x = ""\ny = []'), clear()
|
|
111
|
-
check_completions('x.', 'substr', 'trim')
|
|
112
|
-
check_completions('y.', 'concat', 'push')
|
|
113
|
-
check_completions('x.sl', 'slice')
|
|
114
|
-
send_text('y = {"x":1}'), clear()
|
|
115
|
-
check_completions('y.', 'x')
|
|
116
|
-
|
|
117
|
-
# Test docstrings
|
|
118
|
-
clear()
|
|
119
|
-
send_text('def ds():\n "xxx"\n\n')
|
|
120
|
-
clear()
|
|
121
|
-
check('ds.__doc__', "'xxx'")
|
|
1
|
+
# globals: compiler_dir
|
|
2
|
+
stdout = []
|
|
3
|
+
def clear():
|
|
4
|
+
stdout.length = 0
|
|
5
|
+
|
|
6
|
+
class FakeConsole:
|
|
7
|
+
|
|
8
|
+
def log(self):
|
|
9
|
+
Array.prototype.slice.call(arguments).forEach(def (arg):
|
|
10
|
+
stdout.push((arg or '').toString())
|
|
11
|
+
)
|
|
12
|
+
stdout.push('\n')
|
|
13
|
+
|
|
14
|
+
def error(self):
|
|
15
|
+
Array.prototype.slice.call(arguments).forEach(def (arg):
|
|
16
|
+
stdout.push((arg or '').toString())
|
|
17
|
+
)
|
|
18
|
+
stdout.push('\n')
|
|
19
|
+
|
|
20
|
+
class FakeReadline:
|
|
21
|
+
|
|
22
|
+
def __init__(self):
|
|
23
|
+
self.listeners = {}
|
|
24
|
+
self._prompt = ''
|
|
25
|
+
|
|
26
|
+
def setPrompt(self, prompt):
|
|
27
|
+
self._prompt = prompt
|
|
28
|
+
|
|
29
|
+
def write(self, data):
|
|
30
|
+
stdout.push(data)
|
|
31
|
+
|
|
32
|
+
def clearLine(self):
|
|
33
|
+
pass
|
|
34
|
+
|
|
35
|
+
def on(self, event, callback):
|
|
36
|
+
self.listeners[event] = callback
|
|
37
|
+
return self
|
|
38
|
+
|
|
39
|
+
def prompt(self):
|
|
40
|
+
stdout.push(self._prompt)
|
|
41
|
+
|
|
42
|
+
def send_line(self, text):
|
|
43
|
+
self.listeners['line'](text)
|
|
44
|
+
|
|
45
|
+
repl = require('./repl')
|
|
46
|
+
rl = FakeReadline()
|
|
47
|
+
|
|
48
|
+
send_line = rl.send_line.bind(rl)
|
|
49
|
+
|
|
50
|
+
def send_text(text):
|
|
51
|
+
for line in text.split('\n'):
|
|
52
|
+
send_line(line)
|
|
53
|
+
|
|
54
|
+
def check(text, output):
|
|
55
|
+
send_text(text)
|
|
56
|
+
eq(output, stdout[0])
|
|
57
|
+
clear()
|
|
58
|
+
|
|
59
|
+
def check_in(text, output):
|
|
60
|
+
send_text(text)
|
|
61
|
+
assrt.ok(output in stdout, output + ' not in ' + stdout)
|
|
62
|
+
clear()
|
|
63
|
+
|
|
64
|
+
def check_not_in(text, output):
|
|
65
|
+
send_text(text)
|
|
66
|
+
assrt.ok(output not in stdout)
|
|
67
|
+
clear()
|
|
68
|
+
|
|
69
|
+
readline = {
|
|
70
|
+
'createInterface': def(options):
|
|
71
|
+
rl.completer = options.completer
|
|
72
|
+
return rl
|
|
73
|
+
}
|
|
74
|
+
repl({'lib_path':compiler_dir, 'console':FakeConsole(), 'readline':readline, 'terminal':False, 'show_js':False, 'histfile':False})
|
|
75
|
+
eq = assrt.equal
|
|
76
|
+
eq('>>> ', stdout[-1])
|
|
77
|
+
clear()
|
|
78
|
+
check('1', '1')
|
|
79
|
+
check_in('if 1:\n 2\n \n ', '2')
|
|
80
|
+
check_not_in('if 1:\n 2\n ', '2')
|
|
81
|
+
check_in('1 +\n1\n\n', '2')
|
|
82
|
+
check('max(1, 2)', '2')
|
|
83
|
+
send_text(
|
|
84
|
+
'''
|
|
85
|
+
class A:
|
|
86
|
+
|
|
87
|
+
def __init__(self, a):
|
|
88
|
+
self. a = a
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
''')
|
|
92
|
+
clear()
|
|
93
|
+
check_in('b = A(1)\nb.a', '1')
|
|
94
|
+
check_in('c = A(2)\nc.a', '2')
|
|
95
|
+
send_text('from __python__ import dict_literals\nd={1:1}')
|
|
96
|
+
check_in('isinstance(d, dict)', 'true')
|
|
97
|
+
send_text('from __python__ import no_dict_literals\nd={1:1}')
|
|
98
|
+
check_in('isinstance(d, dict)', 'false')
|
|
99
|
+
# Test completions
|
|
100
|
+
def completions(line):
|
|
101
|
+
return rl.completer(line)[0]
|
|
102
|
+
|
|
103
|
+
def check_completions():
|
|
104
|
+
items = completions(arguments[0])
|
|
105
|
+
for x in Array.prototype.slice.call(arguments, 1):
|
|
106
|
+
assrt.ok(items and x in items, x + ' not in completions for: ' + arguments[0])
|
|
107
|
+
|
|
108
|
+
check_completions('', 'return', 'A')
|
|
109
|
+
check_completions('Array.', 'isArray', 'apply')
|
|
110
|
+
send_text('x = ""\ny = []'), clear()
|
|
111
|
+
check_completions('x.', 'substr', 'trim')
|
|
112
|
+
check_completions('y.', 'concat', 'push')
|
|
113
|
+
check_completions('x.sl', 'slice')
|
|
114
|
+
send_text('y = {"x":1}'), clear()
|
|
115
|
+
check_completions('y.', 'x')
|
|
116
|
+
|
|
117
|
+
# Test docstrings
|
|
118
|
+
clear()
|
|
119
|
+
send_text('def ds():\n "xxx"\n\n')
|
|
120
|
+
clear()
|
|
121
|
+
check('ds.__doc__', "'xxx'")
|
package/test/scoped_flags.pyj
CHANGED
|
@@ -1,76 +1,76 @@
|
|
|
1
|
-
# vim:fileencoding=utf-8
|
|
2
|
-
# License: BSD Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
|
|
3
|
-
|
|
4
|
-
a = {1:1}
|
|
5
|
-
assrt.ok(not isinstance(a, dict))
|
|
6
|
-
|
|
7
|
-
from __python__ import dict_literals, overload_getitem
|
|
8
|
-
a = {1:1}
|
|
9
|
-
assrt.ok(isinstance(a, dict))
|
|
10
|
-
assrt.equal(a[1], 1)
|
|
11
|
-
a[2] = 2
|
|
12
|
-
assrt.equal(a[2], 2)
|
|
13
|
-
a[2] += 4
|
|
14
|
-
assrt.equal(a[2], 6)
|
|
15
|
-
assrt.deepEqual(list(a.keys()), [1, 2])
|
|
16
|
-
from __python__ import no_dict_literals, no_overload_getitem
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
a = {1:1}
|
|
20
|
-
assrt.ok(not isinstance(a, dict))
|
|
21
|
-
|
|
22
|
-
def f():
|
|
23
|
-
from __python__ import dict_literals
|
|
24
|
-
a = {1:1}
|
|
25
|
-
assrt.ok(isinstance(a, dict))
|
|
26
|
-
|
|
27
|
-
a = {1:1}
|
|
28
|
-
assrt.ok(not isinstance(a, dict))
|
|
29
|
-
|
|
30
|
-
class S:
|
|
31
|
-
from __python__ import bound_methods
|
|
32
|
-
|
|
33
|
-
def __init__(self):
|
|
34
|
-
self.a = 3
|
|
35
|
-
|
|
36
|
-
def val(self):
|
|
37
|
-
return self.a if self else None
|
|
38
|
-
|
|
39
|
-
f = S().val
|
|
40
|
-
assrt.equal(f(), S().val())
|
|
41
|
-
|
|
42
|
-
class U:
|
|
43
|
-
|
|
44
|
-
def __init__(self):
|
|
45
|
-
self.a = 3
|
|
46
|
-
|
|
47
|
-
def val(self):
|
|
48
|
-
return self.a if self else None
|
|
49
|
-
|
|
50
|
-
f = U().val
|
|
51
|
-
assrt.equal(f(), None)
|
|
52
|
-
|
|
53
|
-
class C:
|
|
54
|
-
|
|
55
|
-
def __init__(self):
|
|
56
|
-
self.a = 3
|
|
57
|
-
|
|
58
|
-
def uval1(self):
|
|
59
|
-
return self.a if self else None
|
|
60
|
-
|
|
61
|
-
from __python__ import bound_methods
|
|
62
|
-
|
|
63
|
-
def bval(self):
|
|
64
|
-
return self.a
|
|
65
|
-
|
|
66
|
-
from __python__ import no_bound_methods
|
|
67
|
-
|
|
68
|
-
def uval2(self):
|
|
69
|
-
return self.a if self else None
|
|
70
|
-
|
|
71
|
-
c = C()
|
|
72
|
-
u1, u2 = c.uval1, c.uval2
|
|
73
|
-
f = c.bval
|
|
74
|
-
assrt.equal(u1(), None)
|
|
75
|
-
assrt.equal(u2(), None)
|
|
76
|
-
assrt.equal(f(), 3)
|
|
1
|
+
# vim:fileencoding=utf-8
|
|
2
|
+
# License: BSD Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
|
|
3
|
+
|
|
4
|
+
a = {1:1}
|
|
5
|
+
assrt.ok(not isinstance(a, dict))
|
|
6
|
+
|
|
7
|
+
from __python__ import dict_literals, overload_getitem
|
|
8
|
+
a = {1:1}
|
|
9
|
+
assrt.ok(isinstance(a, dict))
|
|
10
|
+
assrt.equal(a[1], 1)
|
|
11
|
+
a[2] = 2
|
|
12
|
+
assrt.equal(a[2], 2)
|
|
13
|
+
a[2] += 4
|
|
14
|
+
assrt.equal(a[2], 6)
|
|
15
|
+
assrt.deepEqual(list(a.keys()), [1, 2])
|
|
16
|
+
from __python__ import no_dict_literals, no_overload_getitem
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
a = {1:1}
|
|
20
|
+
assrt.ok(not isinstance(a, dict))
|
|
21
|
+
|
|
22
|
+
def f():
|
|
23
|
+
from __python__ import dict_literals
|
|
24
|
+
a = {1:1}
|
|
25
|
+
assrt.ok(isinstance(a, dict))
|
|
26
|
+
|
|
27
|
+
a = {1:1}
|
|
28
|
+
assrt.ok(not isinstance(a, dict))
|
|
29
|
+
|
|
30
|
+
class S:
|
|
31
|
+
from __python__ import bound_methods
|
|
32
|
+
|
|
33
|
+
def __init__(self):
|
|
34
|
+
self.a = 3
|
|
35
|
+
|
|
36
|
+
def val(self):
|
|
37
|
+
return self.a if self else None
|
|
38
|
+
|
|
39
|
+
f = S().val
|
|
40
|
+
assrt.equal(f(), S().val())
|
|
41
|
+
|
|
42
|
+
class U:
|
|
43
|
+
|
|
44
|
+
def __init__(self):
|
|
45
|
+
self.a = 3
|
|
46
|
+
|
|
47
|
+
def val(self):
|
|
48
|
+
return self.a if self else None
|
|
49
|
+
|
|
50
|
+
f = U().val
|
|
51
|
+
assrt.equal(f(), None)
|
|
52
|
+
|
|
53
|
+
class C:
|
|
54
|
+
|
|
55
|
+
def __init__(self):
|
|
56
|
+
self.a = 3
|
|
57
|
+
|
|
58
|
+
def uval1(self):
|
|
59
|
+
return self.a if self else None
|
|
60
|
+
|
|
61
|
+
from __python__ import bound_methods
|
|
62
|
+
|
|
63
|
+
def bval(self):
|
|
64
|
+
return self.a
|
|
65
|
+
|
|
66
|
+
from __python__ import no_bound_methods
|
|
67
|
+
|
|
68
|
+
def uval2(self):
|
|
69
|
+
return self.a if self else None
|
|
70
|
+
|
|
71
|
+
c = C()
|
|
72
|
+
u1, u2 = c.uval1, c.uval2
|
|
73
|
+
f = c.bval
|
|
74
|
+
assrt.equal(u1(), None)
|
|
75
|
+
assrt.equal(u2(), None)
|
|
76
|
+
assrt.equal(f(), 3)
|
package/test/str.pyj
CHANGED
|
@@ -221,3 +221,17 @@ ae('{{}}'.format(), '{}')
|
|
|
221
221
|
ae('{x}}}'.format(x=1), '1}')
|
|
222
222
|
a = 1
|
|
223
223
|
ae(f'{{ {a} }}', '{ 1 }')
|
|
224
|
+
|
|
225
|
+
# str.replace — Python semantics (replace all by default)
|
|
226
|
+
ae('bbb', 'aaa'.replace('a', 'b'))
|
|
227
|
+
ae('hello world', 'hello earth'.replace('earth', 'world'))
|
|
228
|
+
ae('baa', 'aaa'.replace('a', 'b', 1))
|
|
229
|
+
ae('bba', 'aaa'.replace('a', 'b', 2))
|
|
230
|
+
ae('aaa', 'aaa'.replace('a', 'b', 0))
|
|
231
|
+
ae('aaa', 'aaa'.replace('x', 'y'))
|
|
232
|
+
ae('', 'aaa'.replace('a', ''))
|
|
233
|
+
ae('xbxbxb', 'ababab'.replace('a', 'x'))
|
|
234
|
+
ae('a$b$c', 'a-b-c'.replace('-', '$'))
|
|
235
|
+
# negative count replaces all (same as omitting count)
|
|
236
|
+
ae('bbb', 'aaa'.replace('a', 'b', -1))
|
|
237
|
+
ae('bbb', 'aaa'.replace('a', 'b', -99))
|