rapydscript-ns 0.8.4 → 0.9.0
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/README.md +715 -169
- package/TODO.md +9 -2
- 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 +36 -27
- package/package.json +1 -1
- package/publish.py +37 -37
- package/release/baselib-plain-pretty.js +2358 -168
- package/release/baselib-plain-ugly.js +73 -3
- package/release/compiler.js +6282 -3092
- package/release/signatures.json +31 -30
- package/session.vim +4 -4
- package/setup.cfg +2 -2
- package/src/ast.pyj +1 -0
- package/src/baselib-builtins.pyj +340 -2
- package/src/baselib-bytes.pyj +664 -0
- package/src/baselib-errors.pyj +1 -1
- package/src/baselib-internal.pyj +267 -60
- package/src/baselib-itertools.pyj +110 -97
- package/src/baselib-str.pyj +22 -4
- package/src/compiler.pyj +36 -36
- package/src/errors.pyj +30 -30
- package/src/lib/abc.pyj +317 -0
- package/src/lib/aes.pyj +646 -646
- package/src/lib/copy.pyj +120 -120
- package/src/lib/dataclasses.pyj +532 -0
- package/src/lib/elementmaker.pyj +83 -83
- package/src/lib/encodings.pyj +126 -126
- package/src/lib/enum.pyj +125 -0
- 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/pythonize.pyj +20 -20
- package/src/lib/random.pyj +118 -118
- package/src/lib/re.pyj +504 -470
- package/src/lib/react.pyj +74 -74
- package/src/lib/traceback.pyj +63 -63
- package/src/lib/typing.pyj +577 -0
- package/src/lib/uuid.pyj +77 -77
- package/src/monaco-language-service/builtins.js +14 -4
- package/src/monaco-language-service/diagnostics.js +19 -20
- package/src/monaco-language-service/dts.js +550 -550
- package/src/output/classes.pyj +62 -26
- package/src/output/comments.pyj +45 -45
- package/src/output/exceptions.pyj +201 -201
- package/src/output/functions.pyj +78 -5
- package/src/output/jsx.pyj +164 -164
- package/src/output/loops.pyj +5 -2
- package/src/output/operators.pyj +100 -34
- package/src/output/treeshake.pyj +182 -182
- package/src/output/utils.pyj +72 -72
- package/src/parse.pyj +80 -16
- package/src/string_interpolation.pyj +72 -72
- package/src/tokenizer.pyj +9 -4
- 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/abc.pyj +291 -0
- package/test/aes_vectors.pyj +421 -421
- package/test/annotations.pyj +80 -80
- package/test/arithmetic_nostrict.pyj +88 -0
- package/test/arithmetic_types.pyj +169 -0
- package/test/baselib.pyj +91 -0
- package/test/bytes.pyj +467 -0
- package/test/classes.pyj +1 -0
- package/test/comparison_ops.pyj +173 -0
- package/test/dataclasses.pyj +253 -0
- package/test/decorators.pyj +77 -77
- package/test/docstrings.pyj +39 -39
- package/test/elementmaker_test.pyj +45 -45
- package/test/enum.pyj +134 -0
- package/test/eval_exec.pyj +56 -0
- package/test/format.pyj +148 -0
- package/test/functions.pyj +151 -151
- package/test/generators.pyj +41 -41
- package/test/generic.pyj +370 -370
- package/test/imports.pyj +72 -72
- 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/object.pyj +64 -0
- package/test/omit_function_metadata.pyj +20 -20
- package/test/python_compat.pyj +17 -15
- package/test/python_features.pyj +70 -15
- package/test/regexp.pyj +83 -55
- package/test/repl.pyj +121 -121
- package/test/scoped_flags.pyj +76 -76
- package/test/tuples.pyj +96 -0
- package/test/typing.pyj +469 -0
- package/test/unit/index.js +116 -7
- package/test/unit/language-service-dts.js +543 -543
- package/test/unit/language-service-hover.js +455 -455
- package/test/unit/language-service.js +84 -0
- package/test/unit/web-repl.js +804 -1
- package/test/vars_locals_globals.pyj +94 -0
- package/tools/cli.js +558 -547
- package/tools/compile.js +224 -219
- package/tools/completer.js +131 -131
- package/tools/embedded_compiler.js +262 -251
- package/tools/gettext.js +185 -185
- package/tools/ini.js +65 -65
- package/tools/lint.js +16 -19
- 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 +252 -252
- 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/PYTHON_DIFFERENCES_REPORT.md +0 -291
- package/PYTHON_FEATURE_COVERAGE.md +0 -200
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})
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# globals: assrt
|
|
2
|
+
# vim:fileencoding=utf-8
|
|
3
|
+
#
|
|
4
|
+
# arithmetic_nostrict.pyj
|
|
5
|
+
# Tests for no_strict_arithmetic: when strict_arithmetic is disabled, incompatible
|
|
6
|
+
# operand types fall back to JavaScript's native coercion instead of raising TypeError.
|
|
7
|
+
# overload_operators must be active for the ρσ_op_*_ns helpers to be dispatched.
|
|
8
|
+
|
|
9
|
+
from __python__ import overload_operators, no_strict_arithmetic
|
|
10
|
+
|
|
11
|
+
ae = assrt.equal
|
|
12
|
+
ade = assrt.deepEqual
|
|
13
|
+
ok = assrt.ok
|
|
14
|
+
|
|
15
|
+
def _no_error(fn):
|
|
16
|
+
try:
|
|
17
|
+
fn()
|
|
18
|
+
return True
|
|
19
|
+
except:
|
|
20
|
+
return False
|
|
21
|
+
|
|
22
|
+
# ── 1. Valid numeric arithmetic still works ───────────────────────────────────
|
|
23
|
+
|
|
24
|
+
ae(1 + 2, 3)
|
|
25
|
+
ae(10 - 3, 7)
|
|
26
|
+
ae(3 * 4, 12)
|
|
27
|
+
ae(7 / 2, 3.5)
|
|
28
|
+
ae(7 // 2, 3)
|
|
29
|
+
ae(7 % 3, 1)
|
|
30
|
+
ae(2 ** 8, 256)
|
|
31
|
+
|
|
32
|
+
# ── 2. Valid string concatenation still works ─────────────────────────────────
|
|
33
|
+
|
|
34
|
+
ae('hello' + ' world', 'hello world')
|
|
35
|
+
|
|
36
|
+
# ── 3. Valid list concatenation still works ───────────────────────────────────
|
|
37
|
+
|
|
38
|
+
ade([1, 2] + [3, 4], [1, 2, 3, 4])
|
|
39
|
+
|
|
40
|
+
# ── 4. String / list repetition still works ──────────────────────────────────
|
|
41
|
+
|
|
42
|
+
ae('ha' * 3, 'hahaha')
|
|
43
|
+
ae(3 * 'ha', 'hahaha')
|
|
44
|
+
ade([0] * 3, [0, 0, 0])
|
|
45
|
+
|
|
46
|
+
# ── 5. Mixed types do NOT raise TypeError ─────────────────────────────────────
|
|
47
|
+
|
|
48
|
+
ok(_no_error(def(): return 1 + 'x';))
|
|
49
|
+
ok(_no_error(def(): return 'x' + 1;))
|
|
50
|
+
ok(_no_error(def(): return 1 - 'x';))
|
|
51
|
+
ok(_no_error(def(): return None + 1;))
|
|
52
|
+
|
|
53
|
+
# ── 6. JS coercion semantics for mixed types ──────────────────────────────────
|
|
54
|
+
|
|
55
|
+
# int + str coerces via JS (number becomes string)
|
|
56
|
+
ae(1 + 'x', '1x')
|
|
57
|
+
ae('x' + 2, 'x2')
|
|
58
|
+
|
|
59
|
+
# number - string coerces string to NaN
|
|
60
|
+
ok(isNaN(1 - 'x'))
|
|
61
|
+
|
|
62
|
+
# ── 7. Dunder methods still dispatch ──────────────────────────────────────────
|
|
63
|
+
|
|
64
|
+
class _Meter:
|
|
65
|
+
def __init__(self, n):
|
|
66
|
+
self.n = n
|
|
67
|
+
def __add__(self, other):
|
|
68
|
+
return _Meter(self.n + other.n)
|
|
69
|
+
def __mul__(self, scalar):
|
|
70
|
+
return _Meter(self.n * scalar)
|
|
71
|
+
|
|
72
|
+
m = _Meter(3) + _Meter(4)
|
|
73
|
+
ae(m.n, 7)
|
|
74
|
+
m2 = _Meter(5) * 2
|
|
75
|
+
ae(m2.n, 10)
|
|
76
|
+
|
|
77
|
+
# ── 8. Augmented assignment does not raise TypeError ──────────────────────────
|
|
78
|
+
|
|
79
|
+
ok(_no_error(def():
|
|
80
|
+
x = 1
|
|
81
|
+
x += 'oops'
|
|
82
|
+
))
|
|
83
|
+
|
|
84
|
+
# ── 9. Comparison operators fall through to JS ────────────────────────────────
|
|
85
|
+
|
|
86
|
+
# JS comparisons with mixed types don't throw; they may produce surprising results
|
|
87
|
+
ok(_no_error(def(): return 1 < 'x';))
|
|
88
|
+
ok(_no_error(def(): return None >= 0;))
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# globals: assrt
|
|
2
|
+
# vim:fileencoding=utf-8
|
|
3
|
+
#
|
|
4
|
+
# arithmetic_types.pyj
|
|
5
|
+
# Tests for Python-style arithmetic type coercion: incompatible operand types
|
|
6
|
+
# raise TypeError instead of silently coercing (as JavaScript would).
|
|
7
|
+
# overload_operators must be active for the ρσ_op_* helpers to be dispatched.
|
|
8
|
+
|
|
9
|
+
from __python__ import overload_operators, strict_arithmetic
|
|
10
|
+
|
|
11
|
+
ae = assrt.equal
|
|
12
|
+
ade = assrt.deepEqual
|
|
13
|
+
ok = assrt.ok
|
|
14
|
+
|
|
15
|
+
def _raises_type_error(fn):
|
|
16
|
+
try:
|
|
17
|
+
fn()
|
|
18
|
+
return False
|
|
19
|
+
except TypeError:
|
|
20
|
+
return True
|
|
21
|
+
|
|
22
|
+
# ── 1. Valid numeric arithmetic ──────────────────────────────────────────────
|
|
23
|
+
|
|
24
|
+
ae(1 + 2, 3)
|
|
25
|
+
ae(1.5 + 2.5, 4.0)
|
|
26
|
+
ae(10 - 3, 7)
|
|
27
|
+
ae(3 * 4, 12)
|
|
28
|
+
ae(7 / 2, 3.5)
|
|
29
|
+
ae(7 // 2, 3)
|
|
30
|
+
ae(7 % 3, 1)
|
|
31
|
+
ae(2 ** 8, 256)
|
|
32
|
+
|
|
33
|
+
# ── 2. Valid string concatenation ────────────────────────────────────────────
|
|
34
|
+
|
|
35
|
+
ae('hello' + ' world', 'hello world')
|
|
36
|
+
ae('a' + 'b' + 'c', 'abc')
|
|
37
|
+
|
|
38
|
+
# ── 3. Valid list concatenation ──────────────────────────────────────────────
|
|
39
|
+
|
|
40
|
+
ade([1, 2] + [3, 4], [1, 2, 3, 4])
|
|
41
|
+
ade([] + [1], [1])
|
|
42
|
+
|
|
43
|
+
# ── 4. Valid string/list repetition ──────────────────────────────────────────
|
|
44
|
+
|
|
45
|
+
ae('ha' * 3, 'hahaha')
|
|
46
|
+
ae(3 * 'ha', 'hahaha')
|
|
47
|
+
ade([0] * 3, [0, 0, 0])
|
|
48
|
+
ade(3 * [1, 2], [1, 2, 1, 2, 1, 2])
|
|
49
|
+
|
|
50
|
+
# ── 5. bool treated as int for arithmetic (Python semantics) ─────────────────
|
|
51
|
+
|
|
52
|
+
ae(True + 1, 2)
|
|
53
|
+
ae(False + 0, 0)
|
|
54
|
+
ae(True + True, 2)
|
|
55
|
+
ae(True * 5, 5)
|
|
56
|
+
ae(False * 100, 0)
|
|
57
|
+
ae(True + 1.5, 2.5)
|
|
58
|
+
|
|
59
|
+
# bool * str and bool * list repetition
|
|
60
|
+
ae(True * 'x', 'x')
|
|
61
|
+
ae(False * 'x', '')
|
|
62
|
+
ade(True * [1, 2], [1, 2])
|
|
63
|
+
ade(False * [1, 2], [])
|
|
64
|
+
|
|
65
|
+
# ── 6. int + str raises TypeError ────────────────────────────────────────────
|
|
66
|
+
|
|
67
|
+
ok(_raises_type_error(def(): return 1 + 'x';))
|
|
68
|
+
ok(_raises_type_error(def(): return 'x' + 1;))
|
|
69
|
+
ok(_raises_type_error(def(): return 1 + '1';))
|
|
70
|
+
|
|
71
|
+
# ── 7. numeric - non-numeric raises TypeError ────────────────────────────────
|
|
72
|
+
|
|
73
|
+
ok(_raises_type_error(def(): return 1 - 'x';))
|
|
74
|
+
ok(_raises_type_error(def(): return 'a' - 'b';))
|
|
75
|
+
ok(_raises_type_error(def(): return [1] - [2];))
|
|
76
|
+
|
|
77
|
+
# ── 8. numeric / non-numeric raises TypeError ────────────────────────────────
|
|
78
|
+
|
|
79
|
+
ok(_raises_type_error(def(): return 1 / 'x';))
|
|
80
|
+
ok(_raises_type_error(def(): return 'a' / 2;))
|
|
81
|
+
|
|
82
|
+
# ── 9. numeric // non-numeric raises TypeError ───────────────────────────────
|
|
83
|
+
|
|
84
|
+
ok(_raises_type_error(def(): return 5 // 'x';))
|
|
85
|
+
ok(_raises_type_error(def(): return 'a' // 2;))
|
|
86
|
+
|
|
87
|
+
# ── 10. numeric % non-numeric raises TypeError ───────────────────────────────
|
|
88
|
+
|
|
89
|
+
ok(_raises_type_error(def(): return 5 % 'x';))
|
|
90
|
+
ok(_raises_type_error(def(): return 'a' % 2;))
|
|
91
|
+
|
|
92
|
+
# ── 11. numeric ** non-numeric raises TypeError ──────────────────────────────
|
|
93
|
+
|
|
94
|
+
ok(_raises_type_error(def(): return 2 ** 'x';))
|
|
95
|
+
ok(_raises_type_error(def(): return 'a' ** 2;))
|
|
96
|
+
|
|
97
|
+
# ── 12. mixed str * non-numeric raises TypeError ─────────────────────────────
|
|
98
|
+
|
|
99
|
+
ok(_raises_type_error(def(): return 'ha' * 'ha';))
|
|
100
|
+
ok(_raises_type_error(def(): return 'ha' * [1];))
|
|
101
|
+
|
|
102
|
+
# ── 13. list + non-list raises TypeError ─────────────────────────────────────
|
|
103
|
+
|
|
104
|
+
ok(_raises_type_error(def(): return [1, 2] + 1;))
|
|
105
|
+
ok(_raises_type_error(def(): return [1, 2] + 'x';))
|
|
106
|
+
ok(_raises_type_error(def(): return 1 + [1, 2];))
|
|
107
|
+
|
|
108
|
+
# ── 14. None as operand raises TypeError ─────────────────────────────────────
|
|
109
|
+
|
|
110
|
+
ok(_raises_type_error(def(): return None + 1;))
|
|
111
|
+
ok(_raises_type_error(def(): return 1 + None;))
|
|
112
|
+
ok(_raises_type_error(def(): return None + 'x';))
|
|
113
|
+
|
|
114
|
+
# ── 15. TypeError message contains operand type names ────────────────────────
|
|
115
|
+
|
|
116
|
+
msg = ''
|
|
117
|
+
try:
|
|
118
|
+
v = 1 + 'x'
|
|
119
|
+
except TypeError as e:
|
|
120
|
+
msg = str(e)
|
|
121
|
+
ok(msg.indexOf('int') >= 0)
|
|
122
|
+
ok(msg.indexOf('str') >= 0)
|
|
123
|
+
ok(msg.indexOf('+') >= 0)
|
|
124
|
+
|
|
125
|
+
msg2 = ''
|
|
126
|
+
try:
|
|
127
|
+
v = 2.5 - 'y'
|
|
128
|
+
except TypeError as e:
|
|
129
|
+
msg2 = str(e)
|
|
130
|
+
ok(msg2.indexOf('float') >= 0)
|
|
131
|
+
ok(msg2.indexOf('str') >= 0)
|
|
132
|
+
ok(msg2.indexOf('-') >= 0)
|
|
133
|
+
|
|
134
|
+
# ── 16. augmented assignment also raises TypeError ───────────────────────────
|
|
135
|
+
|
|
136
|
+
ok(_raises_type_error(def():
|
|
137
|
+
x = 1
|
|
138
|
+
x += 'oops'
|
|
139
|
+
))
|
|
140
|
+
ok(_raises_type_error(def():
|
|
141
|
+
x = 'hello'
|
|
142
|
+
x -= 1
|
|
143
|
+
))
|
|
144
|
+
|
|
145
|
+
# ── 17. dunder methods still take priority over type checks ──────────────────
|
|
146
|
+
|
|
147
|
+
class _Meter:
|
|
148
|
+
def __init__(self, n):
|
|
149
|
+
self.n = n
|
|
150
|
+
def __add__(self, other):
|
|
151
|
+
return _Meter(self.n + other.n)
|
|
152
|
+
def __mul__(self, scalar):
|
|
153
|
+
return _Meter(self.n * scalar)
|
|
154
|
+
|
|
155
|
+
m = _Meter(3) + _Meter(4)
|
|
156
|
+
ae(m.n, 7)
|
|
157
|
+
m2 = _Meter(5) * 2
|
|
158
|
+
ae(m2.n, 10)
|
|
159
|
+
|
|
160
|
+
# ── 18. radd/rsub reflected methods still work ───────────────────────────────
|
|
161
|
+
|
|
162
|
+
class _Vec:
|
|
163
|
+
def __init__(self, x):
|
|
164
|
+
self.x = x
|
|
165
|
+
def __radd__(self, other):
|
|
166
|
+
return _Vec(other + self.x)
|
|
167
|
+
|
|
168
|
+
v = 10 + _Vec(5)
|
|
169
|
+
ae(v.x, 15)
|
package/test/baselib.pyj
CHANGED
|
@@ -99,6 +99,20 @@ assrt.deepEqual(list(map(def(a):return a*2;, iter([1, 2]))), [2, 4])
|
|
|
99
99
|
assrt.deepEqual(list(filter(def(a):return a > 1;, [1, 2])), [2])
|
|
100
100
|
assrt.deepEqual(list(filter(def(a):return a > 1;, iter([1, 2]))), [2])
|
|
101
101
|
assrt.deepEqual(list(zip([1,2], [3,4])), [[1,3], [2, 4]])
|
|
102
|
+
assrt.deepEqual(list(zip([1,2], [3,4], strict=True)), [[1,3], [2, 4]])
|
|
103
|
+
assrt.deepEqual(list(zip(strict=True)), [])
|
|
104
|
+
_zip_err = False
|
|
105
|
+
try:
|
|
106
|
+
list(zip([1,2], [3], strict=True))
|
|
107
|
+
except:
|
|
108
|
+
_zip_err = True
|
|
109
|
+
assrt.ok(_zip_err)
|
|
110
|
+
_zip_err2 = False
|
|
111
|
+
try:
|
|
112
|
+
list(zip([1], [3,4], strict=True))
|
|
113
|
+
except:
|
|
114
|
+
_zip_err2 = True
|
|
115
|
+
assrt.ok(_zip_err2)
|
|
102
116
|
|
|
103
117
|
# lists
|
|
104
118
|
a = [1, 2]
|
|
@@ -317,3 +331,80 @@ assrt.equal(all(iter([1, 2, 3])), True)
|
|
|
317
331
|
assrt.equal(all(iter([1, 0, 3])), False)
|
|
318
332
|
assrt.equal(all(range(1, 4)), True)
|
|
319
333
|
assrt.equal(all(range(0, 3)), False)
|
|
334
|
+
|
|
335
|
+
# complex() builtin and j-literal syntax
|
|
336
|
+
c1 = complex(3, 4)
|
|
337
|
+
assrt.equal(c1.real, 3)
|
|
338
|
+
assrt.equal(c1.imag, 4)
|
|
339
|
+
|
|
340
|
+
# j literal syntax
|
|
341
|
+
c2 = 4j
|
|
342
|
+
assrt.equal(c2.real, 0)
|
|
343
|
+
assrt.equal(c2.imag, 4)
|
|
344
|
+
|
|
345
|
+
# 3+4j literal — + goes through ρσ_list_add which dispatches __add__
|
|
346
|
+
c3 = 3+4j
|
|
347
|
+
assrt.equal(c3.real, 3)
|
|
348
|
+
assrt.equal(c3.imag, 4)
|
|
349
|
+
|
|
350
|
+
# abs() dispatches to __abs__
|
|
351
|
+
assrt.equal(abs(complex(3, 4)), 5.0)
|
|
352
|
+
assrt.equal(abs(complex(-5, 0)), 5)
|
|
353
|
+
|
|
354
|
+
# arithmetic via dunder methods (no overload_operators needed)
|
|
355
|
+
assrt.ok(complex(1, 2).__add__(complex(3, 4)) == complex(4, 6))
|
|
356
|
+
assrt.ok(complex(5, 6).__sub__(complex(3, 4)) == complex(2, 2))
|
|
357
|
+
assrt.ok(complex(1, 2).__mul__(complex(3, 4)) == complex(-5, 10))
|
|
358
|
+
assrt.ok(complex(2, 0).__truediv__(complex(4, 0)) == complex(0.5, 0))
|
|
359
|
+
|
|
360
|
+
# mixed complex + number
|
|
361
|
+
assrt.ok(complex(3, 4) + 1 == complex(4, 4)) # ρσ_list_add → __add__
|
|
362
|
+
assrt.ok(complex(3, 4).__radd__(1) == complex(4, 4))
|
|
363
|
+
assrt.ok(complex(3, 4).__sub__(1) == complex(2, 4))
|
|
364
|
+
assrt.ok(complex(3, 4).__rmul__(2) == complex(6, 8))
|
|
365
|
+
assrt.ok(complex(6, 8).__truediv__(2) == complex(3, 4))
|
|
366
|
+
|
|
367
|
+
# 1 + complex — ρσ_list_add dispatches __radd__ when left has no __add__
|
|
368
|
+
assrt.ok(1 + complex(3, 4) == complex(4, 4))
|
|
369
|
+
|
|
370
|
+
# unary via dunder
|
|
371
|
+
assrt.ok(complex(3, 4).__neg__() == complex(-3, -4))
|
|
372
|
+
assrt.ok(complex(3, 4).__pos__() == complex(3, 4))
|
|
373
|
+
|
|
374
|
+
# conjugate
|
|
375
|
+
assrt.ok(complex(3, 4).conjugate() == complex(3, -4))
|
|
376
|
+
|
|
377
|
+
# zero-argument form
|
|
378
|
+
assrt.ok(complex() == complex(0, 0))
|
|
379
|
+
|
|
380
|
+
# single-argument number
|
|
381
|
+
assrt.ok(complex(5) == complex(5, 0))
|
|
382
|
+
|
|
383
|
+
# single-argument string
|
|
384
|
+
assrt.ok(complex('3+4j') == complex(3, 4))
|
|
385
|
+
assrt.ok(complex('3-4j') == complex(3, -4))
|
|
386
|
+
assrt.ok(complex('4j') == complex(0, 4))
|
|
387
|
+
assrt.ok(complex('3') == complex(3, 0))
|
|
388
|
+
assrt.ok(complex('j') == complex(0, 1))
|
|
389
|
+
assrt.ok(complex('-j') == complex(0, -1))
|
|
390
|
+
|
|
391
|
+
# isinstance
|
|
392
|
+
assrt.ok(isinstance(complex(1, 2), complex))
|
|
393
|
+
assrt.ok(not isinstance(42, complex))
|
|
394
|
+
|
|
395
|
+
# bool — __bool__ dispatch works, and truthiness is correct in conditions
|
|
396
|
+
assrt.ok(complex(0, 0).__bool__() is False)
|
|
397
|
+
assrt.ok(complex(1, 0).__bool__() is True)
|
|
398
|
+
assrt.ok(complex(0, 1).__bool__() is True)
|
|
399
|
+
|
|
400
|
+
# repr / str
|
|
401
|
+
assrt.equal(repr(complex(0, 0)), '0j')
|
|
402
|
+
assrt.equal(repr(complex(1, 0)), '(1+0j)')
|
|
403
|
+
assrt.equal(repr(complex(0, 1)), '1j')
|
|
404
|
+
assrt.equal(repr(complex(3, 4)), '(3+4j)')
|
|
405
|
+
assrt.equal(repr(complex(3, -4)), '(3-4j)')
|
|
406
|
+
assrt.equal(str(complex(3, 4)), '(3+4j)')
|
|
407
|
+
|
|
408
|
+
# abs() still works on numbers
|
|
409
|
+
assrt.equal(abs(-5), 5)
|
|
410
|
+
assrt.equal(abs(3.0), 3.0)
|