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.
Files changed (151) hide show
  1. package/.agignore +1 -1
  2. package/.github/workflows/ci.yml +38 -38
  3. package/=template.pyj +5 -5
  4. package/CHANGELOG.md +19 -0
  5. package/HACKING.md +103 -103
  6. package/LICENSE +24 -24
  7. package/PYTHON_GAPS.md +420 -0
  8. package/README.md +153 -29
  9. package/TODO.md +16 -118
  10. package/add-toc-to-readme +2 -2
  11. package/bin/export +75 -75
  12. package/bin/rapydscript +70 -70
  13. package/bin/web-repl-export +102 -102
  14. package/build +2 -2
  15. package/language-service/index.js +237 -8
  16. package/memory/project_string_impl.md +43 -0
  17. package/package.json +1 -1
  18. package/publish.py +37 -37
  19. package/release/baselib-plain-pretty.js +248 -38
  20. package/release/baselib-plain-ugly.js +8 -8
  21. package/release/compiler.js +778 -277
  22. package/release/signatures.json +30 -30
  23. package/session.vim +4 -4
  24. package/setup.cfg +2 -2
  25. package/src/ast.pyj +4 -1
  26. package/src/baselib-builtins.pyj +56 -2
  27. package/src/baselib-containers.pyj +2 -0
  28. package/src/baselib-errors.pyj +7 -3
  29. package/src/baselib-internal.pyj +51 -6
  30. package/src/baselib-str.pyj +5 -3
  31. package/src/compiler.pyj +36 -36
  32. package/src/errors.pyj +30 -30
  33. package/src/lib/aes.pyj +646 -646
  34. package/src/lib/asyncio.pyj +534 -0
  35. package/src/lib/base64.pyj +399 -0
  36. package/src/lib/bisect.pyj +73 -0
  37. package/src/lib/collections.pyj +1 -1
  38. package/src/lib/copy.pyj +120 -120
  39. package/src/lib/csv.pyj +494 -0
  40. package/src/lib/elementmaker.pyj +83 -83
  41. package/src/lib/encodings.pyj +126 -126
  42. package/src/lib/gettext.pyj +569 -569
  43. package/src/lib/heapq.pyj +98 -0
  44. package/src/lib/html.pyj +382 -0
  45. package/src/lib/http/__init__.pyj +98 -0
  46. package/src/lib/http/client.pyj +304 -0
  47. package/src/lib/http/cookies.pyj +236 -0
  48. package/src/lib/itertools.pyj +580 -580
  49. package/src/lib/logging.pyj +672 -0
  50. package/src/lib/math.pyj +193 -193
  51. package/src/lib/operator.pyj +11 -11
  52. package/src/lib/pythonize.pyj +20 -20
  53. package/src/lib/random.pyj +118 -118
  54. package/src/lib/react.pyj +74 -74
  55. package/src/lib/string.pyj +357 -0
  56. package/src/lib/textwrap.pyj +329 -0
  57. package/src/lib/traceback.pyj +63 -63
  58. package/src/lib/urllib/__init__.pyj +14 -0
  59. package/src/lib/urllib/error.pyj +66 -0
  60. package/src/lib/urllib/parse.pyj +475 -0
  61. package/src/lib/urllib/request.pyj +86 -0
  62. package/src/lib/uuid.pyj +77 -77
  63. package/src/monaco-language-service/analyzer.js +5 -2
  64. package/src/monaco-language-service/completions.js +26 -0
  65. package/src/monaco-language-service/diagnostics.js +202 -3
  66. package/src/monaco-language-service/dts.js +550 -550
  67. package/src/monaco-language-service/scope.js +1 -0
  68. package/src/output/comments.pyj +45 -45
  69. package/src/output/exceptions.pyj +201 -201
  70. package/src/output/functions.pyj +152 -6
  71. package/src/output/jsx.pyj +164 -164
  72. package/src/output/loops.pyj +17 -2
  73. package/src/output/modules.pyj +1 -1
  74. package/src/output/operators.pyj +15 -0
  75. package/src/output/stream.pyj +0 -1
  76. package/src/output/treeshake.pyj +182 -182
  77. package/src/output/utils.pyj +72 -72
  78. package/src/parse.pyj +80 -17
  79. package/src/string_interpolation.pyj +72 -72
  80. package/src/tokenizer.pyj +1 -1
  81. package/src/unicode_aliases.pyj +576 -576
  82. package/src/utils.pyj +192 -192
  83. package/test/_import_one.pyj +37 -37
  84. package/test/_import_two/__init__.pyj +11 -11
  85. package/test/_import_two/level2/deep.pyj +4 -4
  86. package/test/_import_two/other.pyj +6 -6
  87. package/test/_import_two/sub.pyj +13 -13
  88. package/test/aes_vectors.pyj +421 -421
  89. package/test/annotations.pyj +80 -80
  90. package/test/async_generators.pyj +144 -0
  91. package/test/asyncio.pyj +307 -0
  92. package/test/base64.pyj +202 -0
  93. package/test/bisect.pyj +178 -0
  94. package/test/csv.pyj +405 -0
  95. package/test/decorators.pyj +77 -77
  96. package/test/docstrings.pyj +39 -39
  97. package/test/elementmaker_test.pyj +45 -45
  98. package/test/float_special.pyj +64 -0
  99. package/test/functions.pyj +151 -151
  100. package/test/generators.pyj +41 -41
  101. package/test/generic.pyj +370 -370
  102. package/test/heapq.pyj +174 -0
  103. package/test/html.pyj +212 -0
  104. package/test/http.pyj +259 -0
  105. package/test/imports.pyj +79 -72
  106. package/test/internationalization.pyj +73 -73
  107. package/test/lint.pyj +164 -164
  108. package/test/logging.pyj +356 -0
  109. package/test/long.pyj +130 -0
  110. package/test/loops.pyj +85 -85
  111. package/test/numpy.pyj +734 -734
  112. package/test/parenthesized_with.pyj +141 -0
  113. package/test/python_compat.pyj +3 -5
  114. package/test/python_modulo.pyj +76 -0
  115. package/test/python_modulo_off.pyj +21 -0
  116. package/test/repl.pyj +121 -121
  117. package/test/scoped_flags.pyj +76 -76
  118. package/test/str.pyj +14 -0
  119. package/test/string.pyj +245 -0
  120. package/test/textwrap.pyj +172 -0
  121. package/test/type_display.pyj +48 -0
  122. package/test/type_enforcement.pyj +164 -0
  123. package/test/unit/index.js +14 -6
  124. package/test/unit/language-service-completions.js +119 -0
  125. package/test/unit/language-service-dts.js +543 -543
  126. package/test/unit/language-service-hover.js +455 -455
  127. package/test/unit/language-service-scope.js +32 -0
  128. package/test/unit/language-service.js +127 -3
  129. package/test/unit/run-language-service.js +17 -3
  130. package/test/unit/web-repl.js +2094 -29
  131. package/test/urllib.pyj +193 -0
  132. package/tools/compile.js +1 -1
  133. package/tools/compiler.d.ts +367 -367
  134. package/tools/completer.js +131 -131
  135. package/tools/embedded_compiler.js +7 -7
  136. package/tools/gettext.js +185 -185
  137. package/tools/ini.js +65 -65
  138. package/tools/msgfmt.js +187 -187
  139. package/tools/repl.js +223 -223
  140. package/tools/test.js +118 -118
  141. package/tools/utils.js +128 -128
  142. package/tools/web_repl.js +95 -95
  143. package/try +41 -41
  144. package/web-repl/env.js +196 -196
  145. package/web-repl/index.html +163 -163
  146. package/web-repl/main.js +1 -1
  147. package/web-repl/prism.css +139 -139
  148. package/web-repl/prism.js +113 -113
  149. package/web-repl/rapydscript.js +224 -224
  150. package/web-repl/sha1.js +25 -25
  151. 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')
@@ -235,7 +235,7 @@ strings()
235
235
  ae(' hello '.strip(), 'hello')
236
236
  ae('hello world'.upper(), 'HELLO WORLD')
237
237
 
238
- # ── 15. strings() leaves replace() as JS version; split() defaults to ' ' ─────
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
- # Python str.replace() vs JS String.prototype.replace():
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'), 'baa') # JS: replaces only first
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'")
@@ -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))