rapydscript-ns 0.8.2 → 0.8.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 (141) 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 +39 -0
  5. package/HACKING.md +103 -103
  6. package/LICENSE +24 -24
  7. package/PYTHON_DIFFERENCES_REPORT.md +291 -0
  8. package/PYTHON_FEATURE_COVERAGE.md +106 -15
  9. package/README.md +831 -52
  10. package/TODO.md +4 -286
  11. package/add-toc-to-readme +2 -2
  12. package/bin/export +75 -75
  13. package/bin/rapydscript +70 -70
  14. package/bin/web-repl-export +102 -102
  15. package/build +2 -2
  16. package/language-service/index.js +4623 -0
  17. package/language-service/language-service.d.ts +40 -0
  18. package/package.json +9 -7
  19. package/publish.py +37 -37
  20. package/release/baselib-plain-pretty.js +2006 -229
  21. package/release/baselib-plain-ugly.js +70 -3
  22. package/release/compiler.js +11554 -3870
  23. package/release/signatures.json +31 -29
  24. package/session.vim +4 -4
  25. package/setup.cfg +2 -2
  26. package/src/ast.pyj +93 -1
  27. package/src/baselib-builtins.pyj +99 -2
  28. package/src/baselib-containers.pyj +107 -4
  29. package/src/baselib-errors.pyj +44 -0
  30. package/src/baselib-internal.pyj +124 -5
  31. package/src/baselib-itertools.pyj +97 -97
  32. package/src/baselib-str.pyj +32 -1
  33. package/src/compiler.pyj +36 -36
  34. package/src/errors.pyj +30 -30
  35. package/src/lib/aes.pyj +646 -646
  36. package/src/lib/collections.pyj +1 -1
  37. package/src/lib/copy.pyj +120 -0
  38. package/src/lib/elementmaker.pyj +83 -83
  39. package/src/lib/encodings.pyj +126 -126
  40. package/src/lib/gettext.pyj +569 -569
  41. package/src/lib/itertools.pyj +580 -580
  42. package/src/lib/math.pyj +193 -193
  43. package/src/lib/numpy.pyj +10 -10
  44. package/src/lib/operator.pyj +11 -11
  45. package/src/lib/pythonize.pyj +20 -20
  46. package/src/lib/random.pyj +118 -118
  47. package/src/lib/re.pyj +470 -470
  48. package/src/lib/react.pyj +74 -0
  49. package/src/lib/traceback.pyj +63 -63
  50. package/src/lib/uuid.pyj +77 -77
  51. package/src/monaco-language-service/analyzer.js +131 -9
  52. package/src/monaco-language-service/builtins.js +17 -2
  53. package/src/monaco-language-service/completions.js +170 -1
  54. package/src/monaco-language-service/diagnostics.js +25 -3
  55. package/src/monaco-language-service/dts.js +550 -550
  56. package/src/monaco-language-service/index.js +17 -0
  57. package/src/monaco-language-service/scope.js +3 -0
  58. package/src/output/classes.pyj +128 -11
  59. package/src/output/codegen.pyj +17 -3
  60. package/src/output/comments.pyj +45 -45
  61. package/src/output/exceptions.pyj +201 -105
  62. package/src/output/functions.pyj +13 -16
  63. package/src/output/jsx.pyj +164 -0
  64. package/src/output/literals.pyj +28 -2
  65. package/src/output/loops.pyj +0 -9
  66. package/src/output/modules.pyj +2 -5
  67. package/src/output/operators.pyj +22 -2
  68. package/src/output/statements.pyj +2 -2
  69. package/src/output/stream.pyj +1 -13
  70. package/src/output/treeshake.pyj +182 -182
  71. package/src/output/utils.pyj +72 -72
  72. package/src/parse.pyj +434 -114
  73. package/src/string_interpolation.pyj +72 -72
  74. package/src/tokenizer.pyj +29 -0
  75. package/src/unicode_aliases.pyj +576 -576
  76. package/src/utils.pyj +192 -192
  77. package/test/_import_one.pyj +37 -37
  78. package/test/_import_two/__init__.pyj +11 -11
  79. package/test/_import_two/level2/deep.pyj +4 -4
  80. package/test/_import_two/other.pyj +6 -6
  81. package/test/_import_two/sub.pyj +13 -13
  82. package/test/aes_vectors.pyj +421 -421
  83. package/test/annotations.pyj +80 -80
  84. package/test/baselib.pyj +4 -4
  85. package/test/classes.pyj +56 -17
  86. package/test/collections.pyj +5 -5
  87. package/test/decorators.pyj +77 -77
  88. package/test/docstrings.pyj +39 -39
  89. package/test/elementmaker_test.pyj +45 -45
  90. package/test/functions.pyj +151 -151
  91. package/test/generators.pyj +41 -41
  92. package/test/generic.pyj +370 -370
  93. package/test/imports.pyj +72 -72
  94. package/test/internationalization.pyj +73 -73
  95. package/test/lint.pyj +164 -164
  96. package/test/loops.pyj +85 -85
  97. package/test/numpy.pyj +734 -734
  98. package/test/omit_function_metadata.pyj +20 -20
  99. package/test/python_compat.pyj +326 -0
  100. package/test/python_features.pyj +129 -29
  101. package/test/regexp.pyj +55 -55
  102. package/test/repl.pyj +121 -121
  103. package/test/scoped_flags.pyj +76 -76
  104. package/test/slice.pyj +105 -0
  105. package/test/str.pyj +25 -0
  106. package/test/unit/fixtures/fibonacci_expected.js +1 -1
  107. package/test/unit/index.js +2296 -71
  108. package/test/unit/language-service-builtins.js +70 -0
  109. package/test/unit/language-service-bundle.js +5 -5
  110. package/test/unit/language-service-completions.js +180 -0
  111. package/test/unit/language-service-dts.js +543 -543
  112. package/test/unit/language-service-hover.js +455 -455
  113. package/test/unit/language-service-index.js +350 -0
  114. package/test/unit/language-service-scope.js +255 -0
  115. package/test/unit/language-service.js +625 -4
  116. package/test/unit/run-language-service.js +1 -0
  117. package/test/unit/web-repl.js +437 -0
  118. package/tools/build-language-service.js +2 -2
  119. package/tools/cli.js +547 -547
  120. package/tools/compile.js +219 -219
  121. package/tools/compiler.js +0 -24
  122. package/tools/completer.js +131 -131
  123. package/tools/embedded_compiler.js +251 -251
  124. package/tools/export.js +3 -37
  125. package/tools/gettext.js +185 -185
  126. package/tools/ini.js +65 -65
  127. package/tools/msgfmt.js +187 -187
  128. package/tools/repl.js +223 -223
  129. package/tools/test.js +118 -118
  130. package/tools/utils.js +128 -128
  131. package/tools/web_repl.js +95 -95
  132. package/try +41 -41
  133. package/web-repl/env.js +196 -74
  134. package/web-repl/index.html +163 -163
  135. package/web-repl/main.js +252 -254
  136. package/web-repl/prism.css +139 -139
  137. package/web-repl/prism.js +113 -113
  138. package/web-repl/rapydscript.js +227 -139
  139. package/web-repl/sha1.js +25 -25
  140. package/hack_demo.pyj +0 -112
  141. package/web-repl/language-service.js +0 -4187
@@ -36,6 +36,13 @@ class ModelState {
36
36
  this._timer = null;
37
37
  this._scopeMap = null; // most recent ScopeMap for this model
38
38
 
39
+ // Derive the module name from the model URI so this model's content can
40
+ // be registered in _virtualFiles for cross-file import resolution.
41
+ // e.g. URI path "/scripts/utils.py" → module name "utils"
42
+ const uri_path = (model.uri && (model.uri.path || model.uri.fsPath)) || '';
43
+ const basename = uri_path.split('/').pop() || '';
44
+ this._module_name = basename.replace(/\.pyj?x?$/, '') || null;
45
+
39
46
  // Run immediately on first attach
40
47
  this._schedule(0);
41
48
 
@@ -55,6 +62,12 @@ class ModelState {
55
62
  const code = this._model.getValue();
56
63
  const opts = { virtualFiles: service._virtualFiles, stdlibFiles: service._stdlibFiles };
57
64
 
65
+ // Register this model's content in the shared virtualFiles pool so other
66
+ // open models can resolve cross-file imports from it.
67
+ if (this._module_name) {
68
+ service._virtualFiles[this._module_name] = code;
69
+ }
70
+
58
71
  // Diagnostics (syntax errors + lint markers)
59
72
  const markers = service._diagnostics.check(code, {
60
73
  ...opts,
@@ -69,6 +82,10 @@ class ModelState {
69
82
  dispose() {
70
83
  clearTimeout(this._timer);
71
84
  this._subscription.dispose();
85
+ // Remove this model's content from the virtualFiles pool on detach.
86
+ if (this._module_name) {
87
+ delete this._service._virtualFiles[this._module_name];
88
+ }
72
89
  // Clear markers when detaching
73
90
  this._service._monaco.editor.setModelMarkers(this._model, LANGUAGE_ID, []);
74
91
  }
@@ -30,6 +30,9 @@ export class SymbolInfo {
30
30
  this.inferred_class = opts.inferred_class || null; // 'ClassName' when x = ClassName(...)
31
31
  this.dts_call_path = opts.dts_call_path || null; // 'ns.getServer' when x = ns.getServer(...)
32
32
  this.type = null; // Phase 6: TypeInfo
33
+ this.return_type = opts.return_type || null; // annotated return type, e.g. 'list', 'str', 'MyClass'
34
+ this.source_module = opts.source_module || null; // module name when kind='import' (from X import Y)
35
+ this.original_name = opts.original_name || null; // pre-alias name for imports (from X import Y as Z → 'Y')
33
36
  }
34
37
  }
35
38
 
@@ -82,19 +82,75 @@ def print_class(output):
82
82
  output.with_block(def():
83
83
  output.indent()
84
84
  cname = self.name.name
85
- output.print('if (!(this instanceof ' + cname + ')) return new ' + cname + '(...arguments);')
86
- output.newline()
85
+ if self.has_new:
86
+ # When __new__ is defined, call it to get the instance
87
+ output.print('if (!(this instanceof ' + cname + '))')
88
+ output.space()
89
+ output.with_block(def():
90
+ output.indent()
91
+ output.print('var ρσ_instance = ')
92
+ self.name.print(output)
93
+ output.print('.__new__(')
94
+ self.name.print(output)
95
+ output.print(', ...arguments)')
96
+ output.end_statement()
97
+ output.indent()
98
+ output.print('if (ρσ_instance instanceof ')
99
+ self.name.print(output)
100
+ output.print(')')
101
+ output.space()
102
+ output.with_block(def():
103
+ output.indent()
104
+ output.spaced('if', '(ρσ_instance.ρσ_object_id', '===', 'undefined)', 'Object.defineProperty(ρσ_instance,', '"ρσ_object_id",', '{"value":++ρσ_object_counter})')
105
+ output.end_statement()
106
+ if self.bound.length:
107
+ output.indent()
108
+ self.name.print(output), output.print('.prototype.__bind_methods__ && ')
109
+ self.name.print(output), output.print('.prototype.__bind_methods__.call(ρσ_instance)')
110
+ output.end_statement()
111
+ output.indent()
112
+ self.name.print(output)
113
+ output.print('.prototype.__init__.apply(ρσ_instance'), output.comma(), output.print('arguments)')
114
+ output.end_statement()
115
+ )
116
+ output.newline()
117
+ output.indent()
118
+ output.print('return ρσ_instance')
119
+ output.end_statement()
120
+ )
121
+ output.newline()
122
+ else:
123
+ output.print('if (!(this instanceof ' + cname + ')) return new ' + cname + '(...arguments);')
124
+ output.newline()
87
125
  output.indent()
88
126
  output.spaced('if', '(this.ρσ_object_id', '===', 'undefined)', 'Object.defineProperty(this,', '"ρσ_object_id",', '{"value":++ρσ_object_counter})')
89
127
  output.end_statement()
90
- if self.bound.length:
128
+ if self.has_attr_dunders:
129
+ # Wrap in a Proxy so __getattr__/__setattr__/__delattr__/__getattribute__ are triggered.
91
130
  output.indent()
92
- self.name.print(output), output.print(".prototype.__bind_methods__.call(this)")
131
+ output.print('var ρσ_proxy = ρσ_JS_Proxy ? new ρσ_JS_Proxy(this, ρσ_attr_proxy_handler) : this')
132
+ output.end_statement()
133
+ if self.bound.length:
134
+ output.indent()
135
+ self.name.print(output), output.print(".prototype.__bind_methods__ && ")
136
+ self.name.print(output), output.print(".prototype.__bind_methods__.call(ρσ_proxy)")
137
+ output.end_statement()
138
+ output.indent()
139
+ self.name.print(output)
140
+ output.print(".prototype.__init__.apply(ρσ_proxy"), output.comma(), output.print('arguments)')
141
+ output.end_statement()
142
+ output.indent()
143
+ output.print('return ρσ_proxy')
144
+ output.end_statement()
145
+ else:
146
+ if self.bound.length:
147
+ output.indent()
148
+ self.name.print(output), output.print(".prototype.__bind_methods__.call(this)")
149
+ output.end_statement()
150
+ output.indent()
151
+ self.name.print(output)
152
+ output.print(".prototype.__init__.apply(this"), output.comma(), output.print('arguments)')
93
153
  output.end_statement()
94
- output.indent()
95
- self.name.print(output)
96
- output.print(".prototype.__init__.apply(this"), output.comma(), output.print('arguments)')
97
- output.end_statement()
98
154
  )
99
155
 
100
156
  decorators = self.decorators or v'[]'
@@ -214,7 +270,7 @@ def print_class(output):
214
270
  output.end_statement()
215
271
 
216
272
  elif is_node_type(stmt, AST_Class):
217
- console.error('Nested classes aren\'t supported yet') # noqa:undef
273
+ pass # nested classes are emitted in the statements section below
218
274
 
219
275
  if not defined_methods['__repr__']:
220
276
  define_default_method('__repr__', def():
@@ -235,6 +291,13 @@ def print_class(output):
235
291
  output.end_statement()
236
292
  )
237
293
 
294
+ # Python semantics: defining __eq__ without __hash__ makes the class unhashable
295
+ if defined_methods['__eq__'] and not defined_methods['__hash__']:
296
+ output.indent()
297
+ self.name.print(output)
298
+ output.print('.prototype.__hash__ = null')
299
+ output.end_statement()
300
+
238
301
  # Multiple inheritance
239
302
  add_hidden_property('__bases__', def():
240
303
  output.print('[')
@@ -256,6 +319,43 @@ def print_class(output):
256
319
  output.print('.prototype, "__class__", {get: function() { return this.constructor; }, configurable: true})')
257
320
  output.end_statement()
258
321
 
322
+ # __init_subclass__ hook: call after identity properties so cls.__name__ is correct
323
+ if self.parent:
324
+ output.indent()
325
+ output.print('if (typeof ')
326
+ self.parent.print(output)
327
+ output.print('.__init_subclass__ === "function")')
328
+ output.space()
329
+ kws = self.class_kwargs
330
+ if kws and kws.length:
331
+ output.with_block(def():
332
+ output.indent()
333
+ output.print('var ρσ_isc_kw = {')
334
+ for v'var ρσ_kwi = 0; ρσ_kwi < kws.length; ρσ_kwi++':
335
+ if ρσ_kwi > 0:
336
+ output.comma()
337
+ output.print(kws[ρσ_kwi][0].name + ':')
338
+ output.space()
339
+ kws[ρσ_kwi][1].print(output)
340
+ output.print('}')
341
+ output.end_statement()
342
+ output.indent()
343
+ output.print('ρσ_isc_kw[ρσ_kwargs_symbol] = true')
344
+ output.end_statement()
345
+ output.indent()
346
+ self.parent.print(output)
347
+ output.print('.__init_subclass__.call(')
348
+ self.name.print(output)
349
+ output.print(', ρσ_isc_kw)')
350
+ output.end_statement()
351
+ )
352
+ else:
353
+ self.parent.print(output)
354
+ output.print('.__init_subclass__.call(')
355
+ self.name.print(output)
356
+ output.print(')')
357
+ output.end_statement()
358
+
259
359
  if self.bases.length > 1:
260
360
  output.indent()
261
361
  output.print("ρσ_mixin(")
@@ -271,9 +371,26 @@ def print_class(output):
271
371
  output.print(JSON.stringify(create_doctring(self.docstrings)))
272
372
  )
273
373
 
274
- # Other statements in the class context
374
+ # Other statements in the class context (including nested class definitions)
275
375
  for stmt in self.statements:
276
- if not is_node_type(stmt, AST_Method):
376
+ if is_node_type(stmt, AST_Class):
377
+ # Print the nested class in full, then attach it to the outer class.
378
+ # Two assignments mirror Python semantics:
379
+ # Outer.Inner — class-level access (Outer.Inner())
380
+ # Outer.prototype.Inner — instance-level access (self.Inner() inside methods)
381
+ output.indent()
382
+ stmt.print(output)
383
+ output.newline()
384
+ nested_name = stmt.name.name
385
+ output.indent()
386
+ self.name.print(output)
387
+ output.print('.' + nested_name + ' = ' + nested_name)
388
+ output.end_statement()
389
+ output.indent()
390
+ self.name.print(output)
391
+ output.print('.prototype.' + nested_name + ' = ' + nested_name)
392
+ output.end_statement()
393
+ elif not is_node_type(stmt, AST_Method):
277
394
  output.indent()
278
395
  stmt.print(output)
279
396
  output.newline()
@@ -2,7 +2,7 @@
2
2
  # License: BSD Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
3
3
  from __python__ import hash_literals
4
4
 
5
- # globals:console,regenerate,writefile
5
+ # globals:console,writefile
6
6
 
7
7
  from utils import noop
8
8
  from parse import PRECEDENCE
@@ -13,13 +13,14 @@ from ast import (
13
13
  AST_EmptyStatement, AST_Exit, AST_ExpressiveObject, AST_ForIn,
14
14
  AST_ForJS, AST_Function, AST_Hole, AST_If, AST_Imports, AST_Infinity,
15
15
  AST_Lambda, AST_ListComprehension, AST_LoopControl, AST_NaN, AST_NamedExpr, AST_New, AST_Node,
16
- AST_Number, AST_Object, AST_ObjectKeyVal, AST_ObjectProperty, AST_ObjectSpread, AST_PropAccess,
16
+ AST_Number, AST_Object, AST_ObjectKeyVal, AST_ObjectProperty, AST_ObjectSpread, AST_Spread, AST_PropAccess,
17
17
  AST_RegExp, AST_Return, AST_Set, AST_Seq, AST_SimpleStatement, AST_Splice,
18
18
  AST_Statement, AST_StatementWithBody, AST_String, AST_Sub, AST_ItemAccess,
19
19
  AST_Symbol, AST_This, AST_Throw, AST_Toplevel, AST_Try, AST_Unary,
20
20
  AST_UnaryPrefix, AST_Undefined, AST_Var, AST_VarDef, AST_Assert,
21
21
  AST_Verbatim, AST_While, AST_With, AST_Yield, AST_Await, TreeWalker, AST_Existential,
22
- AST_Match, AST_AnnotatedAssign, AST_Super
22
+ AST_Match, AST_AnnotatedAssign, AST_Super,
23
+ AST_JSXElement, AST_JSXFragment, AST_JSXAttribute, AST_JSXSpread, AST_JSXText, AST_JSXExprContainer
23
24
  )
24
25
  from output.exceptions import print_try
25
26
  from output.classes import print_class
@@ -34,6 +35,7 @@ from output.operators import (
34
35
  )
35
36
  from output.functions import print_function, print_function_call
36
37
  from output.statements import print_bracketed, first_in_statement, force_statement, print_with, print_assert, print_match, print_annotated_assign
38
+ from output.jsx import print_jsx_element, print_jsx_fragment, print_jsx_attribute, print_jsx_spread, print_jsx_text, print_jsx_expr_container
37
39
  from output.utils import make_block, make_num
38
40
 
39
41
  # -----[ code generators ]-----
@@ -486,6 +488,10 @@ def generate_code():
486
488
  output.print('**')
487
489
  self.value.print(output)
488
490
  )
491
+ DEFPRINT(AST_Spread, def(self, output):
492
+ output.print('...')
493
+ self.expression.print(output)
494
+ )
489
495
  DEFPRINT(AST_Set, print_set)
490
496
 
491
497
  AST_Symbol.prototype.definition = def():
@@ -525,3 +531,11 @@ def generate_code():
525
531
  output.print(make_num(self.value))
526
532
  )
527
533
  DEFPRINT(AST_RegExp, print_regexp)
534
+
535
+ # -----[ JSX ]-----
536
+ DEFPRINT(AST_JSXElement, print_jsx_element)
537
+ DEFPRINT(AST_JSXFragment, print_jsx_fragment)
538
+ DEFPRINT(AST_JSXAttribute, print_jsx_attribute)
539
+ DEFPRINT(AST_JSXSpread, print_jsx_spread)
540
+ DEFPRINT(AST_JSXText, print_jsx_text)
541
+ DEFPRINT(AST_JSXExprContainer, print_jsx_expr_container)
@@ -1,45 +1,45 @@
1
- # vim:fileencoding=utf-8
2
- # License: BSD Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
3
- from __python__ import hash_literals
4
-
5
- from ast import AST_Exit, is_node_type
6
-
7
-
8
- def output_comments(comments, output, nlb):
9
- for comm in comments:
10
- if comm.type is "comment1":
11
- output.print("//" + comm.value + "\n")
12
- output.indent()
13
- elif comm.type is "comment2":
14
- output.print("/*" + comm.value + "*/")
15
- if nlb:
16
- output.print("\n")
17
- output.indent()
18
- else:
19
- output.space()
20
-
21
-
22
- def print_comments(self, output):
23
- c = output.options.comments
24
- if c:
25
- start = self.start
26
- if start and not start._comments_dumped:
27
- start._comments_dumped = True
28
- comments = start.comments_before
29
- # XXX: ugly fix for https://github.com/mishoo/RapydScript2/issues/112
30
- # if this node is `return` or `throw`, we cannot allow comments before
31
- # the returned or thrown value.
32
- if is_node_type(self, AST_Exit) and self.value and self.value.start.comments_before and self.value.start.comments_before.length > 0:
33
- comments = (comments or v'[]').concat(self.value.start.comments_before)
34
- self.value.start.comments_before = v'[]'
35
-
36
- if c.test:
37
- comments = comments.filter(def(comment):
38
- return c.test(comment.value)
39
- )
40
- elif jstype(c) is "function":
41
- comments = comments.filter(def(comment):
42
- return c(self, comment)
43
- )
44
-
45
- output_comments(comments, output, start.nlb)
1
+ # vim:fileencoding=utf-8
2
+ # License: BSD Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
3
+ from __python__ import hash_literals
4
+
5
+ from ast import AST_Exit, is_node_type
6
+
7
+
8
+ def output_comments(comments, output, nlb):
9
+ for comm in comments:
10
+ if comm.type is "comment1":
11
+ output.print("//" + comm.value + "\n")
12
+ output.indent()
13
+ elif comm.type is "comment2":
14
+ output.print("/*" + comm.value + "*/")
15
+ if nlb:
16
+ output.print("\n")
17
+ output.indent()
18
+ else:
19
+ output.space()
20
+
21
+
22
+ def print_comments(self, output):
23
+ c = output.options.comments
24
+ if c:
25
+ start = self.start
26
+ if start and not start._comments_dumped:
27
+ start._comments_dumped = True
28
+ comments = start.comments_before
29
+ # XXX: ugly fix for https://github.com/mishoo/RapydScript2/issues/112
30
+ # if this node is `return` or `throw`, we cannot allow comments before
31
+ # the returned or thrown value.
32
+ if is_node_type(self, AST_Exit) and self.value and self.value.start.comments_before and self.value.start.comments_before.length > 0:
33
+ comments = (comments or v'[]').concat(self.value.start.comments_before)
34
+ self.value.start.comments_before = v'[]'
35
+
36
+ if c.test:
37
+ comments = comments.filter(def(comment):
38
+ return c.test(comment.value)
39
+ )
40
+ elif jstype(c) is "function":
41
+ comments = comments.filter(def(comment):
42
+ return c(self, comment)
43
+ )
44
+
45
+ output_comments(comments, output, start.nlb)