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,193 @@
1
+ # globals: assrt
2
+ # vim:fileencoding=utf-8
3
+ #
4
+ # urllib.pyj
5
+ # Tests for the urllib standard library module.
6
+ #
7
+ # Covers urllib.parse (pure-JS, no network) and urllib.error exception classes.
8
+ # urllib.request requires a live network (Fetch API) so it is exercised only
9
+ # in the web-repl bundle tests via a mocked Promise chain.
10
+
11
+ from urllib.parse import (
12
+ quote, unquote, quote_plus, unquote_plus,
13
+ urlencode, urlsplit, urlunsplit, urlparse, urlunparse,
14
+ urljoin, parse_qs, parse_qsl,
15
+ SplitResult, ParseResult
16
+ )
17
+ from urllib.error import URLError, HTTPError
18
+
19
+ ae = assrt.equal
20
+ ade = assrt.deepEqual
21
+ ok = assrt.ok
22
+
23
+ # ── 1. quote — basic percent-encoding ────────────────────────────────────────
24
+
25
+ ae(quote('hello world'), 'hello%20world')
26
+ ae(quote('a/b/c'), 'a/b/c') # '/' is safe by default
27
+ ae(quote('a/b/c', safe=''), 'a%2Fb%2Fc')
28
+ ae(quote('abc123-_.~'), 'abc123-_.~') # unreserved chars pass through
29
+ ae(quote('a+b'), 'a%2Bb')
30
+ ae(quote('a=1&b=2', safe=''), 'a%3D1%26b%3D2')
31
+ ae(quote('!*\'()'), '%21%2A%27%28%29') # sub-delimiters encoded
32
+
33
+ # ── 2. unquote ────────────────────────────────────────────────────────────────
34
+
35
+ ae(unquote('hello%20world'), 'hello world')
36
+ ae(unquote('a%2Fb'), 'a/b')
37
+ ae(unquote('abc'), 'abc')
38
+ ae(unquote('a%2Bb'), 'a+b') # '+' is not decoded by unquote
39
+
40
+ # ── 3. quote_plus / unquote_plus ─────────────────────────────────────────────
41
+
42
+ ae(quote_plus('hello world'), 'hello+world')
43
+ ae(quote_plus('a+b'), 'a%2Bb')
44
+ ae(quote_plus('a/b', safe=''), 'a%2Fb')
45
+ ae(unquote_plus('hello+world'), 'hello world')
46
+ ae(unquote_plus('a%2Bb'), 'a+b')
47
+ ae(unquote_plus('hello%20world'), 'hello world')
48
+
49
+ # ── 4. urlencode — list of pairs ─────────────────────────────────────────────
50
+
51
+ ae(urlencode([['a', '1'], ['b', '2']]), 'a=1&b=2')
52
+ ae(urlencode([['q', 'hello world']]), 'q=hello%20world')
53
+ ae(urlencode([['k', 'a+b']]), 'k=a%2Bb')
54
+ ae(urlencode([]), '')
55
+
56
+ # ── 5. urlencode — doseq ─────────────────────────────────────────────────────
57
+
58
+ ae(urlencode([['a', ['x', 'y']]], doseq=True), 'a=x&a=y')
59
+ ae(urlencode([['a', ['x', 'y']], ['b', '1']], doseq=True), 'a=x&a=y&b=1')
60
+
61
+ # ── 6. urlsplit — absolute URL ────────────────────────────────────────────────
62
+
63
+ r = urlsplit('http://example.com/path?q=1#frag')
64
+ ae(r.scheme, 'http')
65
+ ae(r.netloc, 'example.com')
66
+ ae(r.path, '/path')
67
+ ae(r.query, 'q=1')
68
+ ae(r.fragment, 'frag')
69
+ ae(r.hostname, 'example.com')
70
+ ae(r.port, None)
71
+ ae(r.username, None)
72
+ ae(r.password, None)
73
+
74
+ # ── 7. urlsplit — authority with user:pass@host:port ─────────────────────────
75
+
76
+ r2 = urlsplit('https://user:pw@host:8080/p?x=1')
77
+ ae(r2.scheme, 'https')
78
+ ae(r2.netloc, 'user:pw@host:8080')
79
+ ae(r2.path, '/p')
80
+ ae(r2.query, 'x=1')
81
+ ae(r2.hostname, 'host')
82
+ ae(r2.port, 8080)
83
+ ae(r2.username, 'user')
84
+ ae(r2.password, 'pw')
85
+
86
+ # ── 8. urlsplit — no fragment ─────────────────────────────────────────────────
87
+
88
+ r3 = urlsplit('http://example.com/path?q=1', allow_fragments=False)
89
+ ae(r3.fragment, '')
90
+ ae(r3.query, 'q=1')
91
+
92
+ # ── 9. urlsplit — relative URL ────────────────────────────────────────────────
93
+
94
+ r4 = urlsplit('/path?q=1#frag')
95
+ ae(r4.scheme, '')
96
+ ae(r4.netloc, '')
97
+ ae(r4.path, '/path')
98
+ ae(r4.query, 'q=1')
99
+ ae(r4.fragment, 'frag')
100
+
101
+ # ── 10. urlparse — params split from path ─────────────────────────────────────
102
+
103
+ r5 = urlparse('http://example.com/path;params?q=1#frag')
104
+ ae(r5.scheme, 'http')
105
+ ae(r5.path, '/path')
106
+ ae(r5.params, 'params')
107
+ ae(r5.query, 'q=1')
108
+ ae(r5.fragment, 'frag')
109
+
110
+ r6 = urlparse('http://example.com/path?q=1')
111
+ ae(r6.params, '')
112
+
113
+ # ── 11. urlunsplit / urlunparse ───────────────────────────────────────────────
114
+
115
+ ae(urlunsplit(('http', 'example.com', '/path', 'q=1', 'frag')),
116
+ 'http://example.com/path?q=1#frag')
117
+ ae(urlunsplit(('http', 'example.com', '/path', '', '')),
118
+ 'http://example.com/path')
119
+ ae(urlunsplit(('', '', '/path', 'q=1', '')),
120
+ '/path?q=1')
121
+ ae(urlunparse(('http', 'example.com', '/path', 'par', 'q=1', 'frag')),
122
+ 'http://example.com/path;par?q=1#frag')
123
+ ae(urlunparse(('http', 'example.com', '/path', '', 'q=1', '')),
124
+ 'http://example.com/path?q=1')
125
+
126
+ # ── 12. geturl round-trip ─────────────────────────────────────────────────────
127
+
128
+ r7 = urlsplit('http://example.com/path?q=1#frag')
129
+ ae(r7.geturl(), 'http://example.com/path?q=1#frag')
130
+
131
+ r8 = urlparse('http://example.com/path?q=1#frag')
132
+ ae(r8.geturl(), 'http://example.com/path?q=1#frag')
133
+
134
+ # ── 13. urljoin ───────────────────────────────────────────────────────────────
135
+
136
+ ae(urljoin('http://example.com/foo', 'bar'), 'http://example.com/bar')
137
+ ae(urljoin('http://example.com/foo/', 'bar'), 'http://example.com/foo/bar')
138
+ ae(urljoin('http://example.com/', '/other'), 'http://example.com/other')
139
+ ae(urljoin('http://example.com/foo', 'http://other.com/'), 'http://other.com/')
140
+ ae(urljoin('http://example.com/foo', '?q=1'), 'http://example.com/foo?q=1')
141
+
142
+ # ── 14. parse_qsl ─────────────────────────────────────────────────────────────
143
+
144
+ pairs = parse_qsl('a=1&b=2&a=3')
145
+ ade(pairs[0], ['a', '1'])
146
+ ade(pairs[1], ['b', '2'])
147
+ ade(pairs[2], ['a', '3'])
148
+ ae(len(pairs), 3)
149
+
150
+ pairs2 = parse_qsl('a=hello+world')
151
+ ae(len(pairs2), 1)
152
+ ae(pairs2[0][1], 'hello world')
153
+
154
+ pairs3 = parse_qsl('q=a%20b')
155
+ ae(pairs3[0][1], 'a b')
156
+
157
+ ae(len(parse_qsl('')), 0)
158
+
159
+ # ── 15. parse_qs ─────────────────────────────────────────────────────────────
160
+
161
+ d = parse_qs('a=1&b=2&a=3')
162
+ ade(d['a'], ['1', '3'])
163
+ ade(d['b'], ['2'])
164
+
165
+ d2 = parse_qs('q=hello+world')
166
+ ae(d2['q'][0], 'hello world')
167
+
168
+ ae(len(parse_qs('')), 0)
169
+
170
+ # ── 16. URLError / HTTPError ──────────────────────────────────────────────────
171
+
172
+ try:
173
+ raise URLError('network error')
174
+ ok(False)
175
+ except URLError as e:
176
+ ok('network error' in str(e.reason))
177
+
178
+ try:
179
+ raise HTTPError('http://example.com', 404, 'Not Found', {}, None)
180
+ ok(False)
181
+ except HTTPError as e:
182
+ ae(e.code, 404)
183
+ ae(e.msg, 'Not Found')
184
+ ae(e.getcode(), 404)
185
+ ae(e.geturl(), 'http://example.com')
186
+ ok(isinstance(e, URLError))
187
+
188
+ try:
189
+ raise HTTPError('http://example.com', 500, 'Internal Server Error', {}, None)
190
+ ok(False)
191
+ except URLError as e:
192
+ # HTTPError is caught by URLError handler (inheritance)
193
+ ae(e.code, 500)
package/tools/compile.js CHANGED
@@ -76,7 +76,7 @@ module.exports = function(start_time, argv, base_path, src_path, lib_path) {
76
76
 
77
77
  var global_scoped_flags = build_scoped_flags(argv.python_flags);
78
78
  if (!argv.legacy_rapydscript) {
79
- var python_mode_flags = ['dict_literals', 'overload_getitem', 'bound_methods', 'hash_literals', 'overload_operators', 'truthiness', 'jsx'];
79
+ var python_mode_flags = ['dict_literals', 'overload_getitem', 'bound_methods', 'hash_literals', 'overload_operators', 'truthiness', 'jsx', 'type_enforcement'];
80
80
  python_mode_flags.forEach(function(f) { if (!(f in global_scoped_flags)) global_scoped_flags[f] = true; });
81
81
  if (!argv.pythonize_strings) OUTPUT_OPTIONS.pythonize_strings = true;
82
82
  }
@@ -7,7 +7,7 @@
7
7
  "use strict"; /*jshint node:true */
8
8
 
9
9
  var has_prop = Object.prototype.hasOwnProperty.call.bind(Object.prototype.hasOwnProperty);
10
- var PYTHON_MODE_FLAGS = ['dict_literals', 'overload_getitem', 'bound_methods', 'hash_literals', 'overload_operators', 'truthiness', 'jsx'];
10
+ var PYTHON_MODE_FLAGS = ['dict_literals', 'overload_getitem', 'bound_methods', 'hash_literals', 'overload_operators', 'truthiness', 'jsx', 'type_enforcement'];
11
11
 
12
12
  function build_scoped_flags(flags_str) {
13
13
  var result = Object.create(null);
@@ -28,8 +28,8 @@ module.exports = function(compiler, baselib, runjs, name, vf_context) {
28
28
  runjs(print_ast(compiler.parse(''), true));
29
29
  runjs('var __name__ = "' + (name || '__embedded__') + '";');
30
30
 
31
- function print_ast(ast, keep_baselib, keep_docstrings, js_version, private_scope, write_name, omit_function_metadata, pythonize_strings) {
32
- var output_options = {omit_baselib:!keep_baselib, write_name:!!write_name, private_scope:!!private_scope, beautify:true, js_version: (js_version || 6), keep_docstrings:keep_docstrings, omit_function_metadata:!!omit_function_metadata, pythonize_strings:!!pythonize_strings};
31
+ function print_ast(ast, keep_baselib, keep_docstrings, js_version, private_scope, write_name, pythonize_strings) {
32
+ var output_options = {omit_baselib:!keep_baselib, write_name:!!write_name, private_scope:!!private_scope, beautify:true, js_version: (js_version || 6), keep_docstrings:keep_docstrings, pythonize_strings:!!pythonize_strings};
33
33
  if (keep_baselib) output_options.baselib_plain = baselib;
34
34
  var output = new compiler.OutputStream(output_options);
35
35
  ast.print(output);
@@ -105,8 +105,8 @@ module.exports = function(compiler, baselib, runjs, name, vf_context) {
105
105
  });
106
106
  }
107
107
 
108
- function print_ast_with_sourcemap(ast, keep_baselib, keep_docstrings, js_version, private_scope, write_name, omit_function_metadata, pythonize_strings, source_name, source_content) {
109
- var output_options = {omit_baselib:!keep_baselib, write_name:!!write_name, private_scope:!!private_scope, beautify:true, js_version:(js_version||6), keep_docstrings:keep_docstrings, omit_function_metadata:!!omit_function_metadata, pythonize_strings:!!pythonize_strings};
108
+ function print_ast_with_sourcemap(ast, keep_baselib, keep_docstrings, js_version, private_scope, write_name, pythonize_strings, source_name, source_content) {
109
+ var output_options = {omit_baselib:!keep_baselib, write_name:!!write_name, private_scope:!!private_scope, beautify:true, js_version:(js_version||6), keep_docstrings:keep_docstrings, pythonize_strings:!!pythonize_strings};
110
110
  if (keep_baselib) output_options.baselib_plain = baselib;
111
111
  var raw_mappings = [];
112
112
  var output = new compiler.OutputStream(output_options);
@@ -171,7 +171,7 @@ module.exports = function(compiler, baselib, runjs, name, vf_context) {
171
171
  });
172
172
  }
173
173
  var pythonize_strings = (opts.legacy_rapydscript !== true) ? true : !!opts.pythonize_strings;
174
- var ans = print_ast(this.toplevel, opts.keep_baselib, opts.keep_docstrings, opts.js_version, opts.private_scope, opts.write_name, opts.omit_function_metadata, pythonize_strings);
174
+ var ans = print_ast(this.toplevel, opts.keep_baselib, opts.keep_docstrings, opts.js_version, opts.private_scope, opts.write_name, pythonize_strings);
175
175
  if (opts.export_main) {
176
176
  ans = ans.replace(/^(function\smain)/gm, 'export $1')
177
177
  .replace(/^(async\sfunction\smain)/gm, 'export $1');
@@ -233,7 +233,7 @@ module.exports = function(compiler, baselib, runjs, name, vf_context) {
233
233
  var result = print_ast_with_sourcemap(
234
234
  this.toplevel,
235
235
  opts.keep_baselib, opts.keep_docstrings, opts.js_version,
236
- opts.private_scope, opts.write_name, opts.omit_function_metadata,
236
+ opts.private_scope, opts.write_name,
237
237
  pythonize_strings_sm,
238
238
  opts.filename || '<input>',
239
239
  code
package/tools/export.js CHANGED
@@ -229,7 +229,8 @@ function compile(code, filename, options) {
229
229
 
230
230
  function create_embedded_compiler(runjs) {
231
231
  var c = vrequire('tools/embedded_compiler.js');
232
- return c(create_compiler(), data['baselib-plain-pretty.js'], runjs);
232
+ if (!RapydScript) RapydScript = create_compiler();
233
+ return c(RapydScript, data['baselib-plain-pretty.js'], runjs);
233
234
  }
234
235
 
235
236
  function web_repl() {
@@ -238,7 +239,8 @@ function web_repl() {
238
239
  set: function(vf) { current_virtual_files = vf; },
239
240
  clear: function() { current_virtual_files = null; }
240
241
  };
241
- return repl(create_compiler(), data['baselib-plain-pretty.js'], vf_context);
242
+ if (!RapydScript) RapydScript = create_compiler();
243
+ return repl(RapydScript, data['baselib-plain-pretty.js'], vf_context);
242
244
  }
243
245
 
244
246
  function init_repl(options) {
package/web-repl/main.js CHANGED
@@ -18,7 +18,7 @@
18
18
  };
19
19
 
20
20
  function compile(code) {
21
- return web_repl.compile(code, {omit_function_metadata: false, tree_shake: false, export_main: true, virtual_files: VIRTUAL_FILES, legacy_rapydscript: false});
21
+ return web_repl.compile(code, {tree_shake: false, export_main: true, virtual_files: VIRTUAL_FILES, legacy_rapydscript: false});
22
22
  }
23
23
 
24
24
  function runjs(code) {