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
@@ -119,6 +119,70 @@ function run_js(js) {
119
119
  });
120
120
  }
121
121
 
122
+ // Minimal React stub — mirrors the one in web-repl/env.js so that compiled
123
+ // code that imports from the react library can run in a plain Node vm context.
124
+ var REACT_STUB = (function () {
125
+ var Fragment = Symbol("React.Fragment");
126
+ function createElement(type, props) {
127
+ var children = Array.prototype.slice.call(arguments, 2);
128
+ return { type: type, props: Object.assign({ children: children.length === 1 ? children[0] : children }, props) };
129
+ }
130
+ function useState(initial) {
131
+ var s = typeof initial === "function" ? initial() : initial;
132
+ return [s, function (v) { s = typeof v === "function" ? v(s) : v; }];
133
+ }
134
+ function useEffect(fn) { fn(); }
135
+ function useLayoutEffect(fn) { fn(); }
136
+ function useMemo(fn) { return fn(); }
137
+ function useCallback(fn) { return fn; }
138
+ function useRef(initial) { return { current: initial }; }
139
+ function useContext(ctx) { return ctx && ctx._currentValue !== undefined ? ctx._currentValue : undefined; }
140
+ function useReducer(reducer, initial) { return [initial, function (a) {}]; }
141
+ function useImperativeHandle(ref, create) { if (ref) ref.current = create(); }
142
+ function useDebugValue() {}
143
+ function useId() { return ":r" + (Math.random() * 1e9 | 0) + ":"; }
144
+ function useTransition() { return [false, function (fn) { fn(); }]; }
145
+ function useDeferredValue(v) { return v; }
146
+ function useSyncExternalStore(sub, get) { return get(); }
147
+ function useInsertionEffect(fn) { fn(); }
148
+ function createContext(def) { return { _currentValue: def }; }
149
+ function createRef() { return { current: null }; }
150
+ function forwardRef(render) { return function (props) { return render(props, null); }; }
151
+ function memo(C) { return C; }
152
+ function lazy(f) { return f; }
153
+ function cloneElement(el, props) { return Object.assign({}, el, { props: Object.assign({}, el.props, props) }); }
154
+ function isValidElement(o) { return o !== null && typeof o === "object" && o.type !== undefined; }
155
+ function Component() {}
156
+ Component.prototype.setState = function (u) { this.state = Object.assign({}, this.state, typeof u === "function" ? u(this.state) : u); };
157
+ function PureComponent() {}
158
+ PureComponent.prototype = Object.create(Component.prototype);
159
+ PureComponent.prototype.constructor = PureComponent;
160
+ return {
161
+ Fragment: Fragment, createElement: createElement,
162
+ useState: useState, useEffect: useEffect, useLayoutEffect: useLayoutEffect,
163
+ useMemo: useMemo, useCallback: useCallback, useRef: useRef,
164
+ useContext: useContext, useReducer: useReducer,
165
+ useImperativeHandle: useImperativeHandle, useDebugValue: useDebugValue,
166
+ useId: useId, useTransition: useTransition, useDeferredValue: useDeferredValue,
167
+ useSyncExternalStore: useSyncExternalStore, useInsertionEffect: useInsertionEffect,
168
+ createContext: createContext, createRef: createRef, forwardRef: forwardRef,
169
+ memo: memo, lazy: lazy, cloneElement: cloneElement, isValidElement: isValidElement,
170
+ Component: Component, PureComponent: PureComponent,
171
+ StrictMode: {}, Suspense: {}, Profiler: {},
172
+ };
173
+ })();
174
+
175
+ // Run compiled JS in a vm context that also has a React stub available.
176
+ function run_js_with_react(js) {
177
+ return vm.runInNewContext(js, {
178
+ __name__ : "<test>",
179
+ console : console,
180
+ assrt : assert,
181
+ ρσ_last_exception : undefined,
182
+ React : REACT_STUB,
183
+ });
184
+ }
185
+
122
186
  // ---------------------------------------------------------------------------
123
187
  // Tests
124
188
  // ---------------------------------------------------------------------------
@@ -445,6 +509,379 @@ var TESTS = [
445
509
  },
446
510
  },
447
511
 
512
+ {
513
+ name: "nested_class_web_repl",
514
+ description: "Nested class definitions compile and run correctly via the web-repl bundle",
515
+ run: function () {
516
+ var repl = RS.web_repl();
517
+ var js = bundle_compile(repl, [
518
+ "class Outer:",
519
+ " class Inner:",
520
+ " def __init__(self, val):",
521
+ " self.val = val",
522
+ " def __init__(self, v):",
523
+ " self.inner = Outer.Inner(v)",
524
+ "o = Outer(99)",
525
+ "assrt.equal(o.inner.val, 99)",
526
+ "assrt.ok(isinstance(o.inner, Outer.Inner))",
527
+ "assrt.ok(o.Inner is Outer.Inner)",
528
+ ].join("\n"));
529
+ run_js(js);
530
+ },
531
+ },
532
+
533
+ // ── slice() builtin ───────────────────────────────────────────────────
534
+
535
+ {
536
+ name: "bundle_slice_constructor",
537
+ description: "slice() constructor stores start/stop/step attributes correctly",
538
+ run: function () {
539
+ var repl = RS.web_repl();
540
+ var js = bundle_compile(repl, [
541
+ "s1 = slice(5)",
542
+ "assrt.equal(s1.start, None)",
543
+ "assrt.equal(s1.stop, 5)",
544
+ "assrt.equal(s1.step, None)",
545
+ "s2 = slice(2, 8)",
546
+ "assrt.equal(s2.start, 2)",
547
+ "assrt.equal(s2.stop, 8)",
548
+ "assrt.equal(s2.step, None)",
549
+ "s3 = slice(1, 9, 2)",
550
+ "assrt.equal(s3.start, 1)",
551
+ "assrt.equal(s3.stop, 9)",
552
+ "assrt.equal(s3.step, 2)",
553
+ ].join("\n"));
554
+ run_js(js);
555
+ },
556
+ },
557
+
558
+ {
559
+ name: "bundle_slice_subscript",
560
+ description: "slice object used as list subscript returns the correct sub-list",
561
+ run: function () {
562
+ var repl = RS.web_repl();
563
+ var js = bundle_compile(repl, [
564
+ "from __python__ import overload_getitem",
565
+ "lst = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]",
566
+ "s = slice(2, 5)",
567
+ "assrt.deepEqual(lst[s], [2, 3, 4])",
568
+ "assrt.deepEqual(lst[slice(0, 6, 2)], [0, 2, 4])",
569
+ "assrt.deepEqual(lst[slice(5, 1, -1)], [5, 4, 3, 2])",
570
+ ].join("\n"));
571
+ run_js(js);
572
+ },
573
+ },
574
+
575
+ {
576
+ name: "bundle_slice_indices",
577
+ description: "slice.indices() returns normalised (start, stop, step) tuple",
578
+ run: function () {
579
+ var repl = RS.web_repl();
580
+ var js = bundle_compile(repl, [
581
+ "s = slice(2, 8)",
582
+ "idx = s.indices(10)",
583
+ "assrt.equal(idx[0], 2)",
584
+ "assrt.equal(idx[1], 8)",
585
+ "assrt.equal(idx[2], 1)",
586
+ "# negative indices normalised",
587
+ "s2 = slice(-3, -1)",
588
+ "idx2 = s2.indices(10)",
589
+ "assrt.equal(idx2[0], 7)",
590
+ "assrt.equal(idx2[1], 9)",
591
+ ].join("\n"));
592
+ run_js(js);
593
+ },
594
+ },
595
+
596
+ {
597
+ name: "bundle_slice_repr",
598
+ description: "str(slice(...)) produces the Python-style repr",
599
+ run: function () {
600
+ var repl = RS.web_repl();
601
+ var js = bundle_compile(repl, [
602
+ "assrt.equal(str(slice(1, 5, None)), 'slice(1, 5, None)')",
603
+ "assrt.equal(str(slice(None, 5, 2)), 'slice(None, 5, 2)')",
604
+ ].join("\n"));
605
+ run_js(js);
606
+ },
607
+ },
608
+
609
+ {
610
+ name: "bundle_slice_isinstance",
611
+ description: "isinstance(slice(...), slice) returns True in bundled baselib",
612
+ run: function () {
613
+ var repl = RS.web_repl();
614
+ var js = bundle_compile(repl, [
615
+ "s = slice(1, 5)",
616
+ "assrt.ok(isinstance(s, slice))",
617
+ ].join("\n"));
618
+ run_js(js);
619
+ },
620
+ },
621
+
622
+ {
623
+ name: "bundle_tuple_annotation_variable",
624
+ description: "variable type annotation with tuple does not become a function call",
625
+ run: function () {
626
+ var repl = RS.web_repl();
627
+ var js = bundle_compile(repl, [
628
+ "# globals: assrt",
629
+ "range_limits: tuple = (0, 100)",
630
+ "assrt.equal(range_limits[0], 0)",
631
+ "assrt.equal(range_limits[1], 100)",
632
+ ].join("\n"));
633
+ // Ensure it compiled to an assignment, not a call
634
+ if (/range_limits\s*\(/.test(js)) throw new Error("range_limits was compiled as a function call:\n" + js);
635
+ run_js(js);
636
+ },
637
+ },
638
+
639
+ {
640
+ name: "bundle_tuple_annotation_function_arg",
641
+ description: "function argument type annotation with tuple and int works at runtime",
642
+ run: function () {
643
+ var repl = RS.web_repl();
644
+ var js = bundle_compile(repl, [
645
+ "# globals: assrt",
646
+ "def clamp(val: int, bounds: tuple) -> int:",
647
+ " lo, hi = bounds",
648
+ " return max(lo, min(hi, val))",
649
+ "range_limits: tuple = (0, 100)",
650
+ "assrt.equal(clamp(150, range_limits), 100)",
651
+ "assrt.equal(clamp(-5, range_limits), 0)",
652
+ ].join("\n"));
653
+ run_js(js);
654
+ },
655
+ },
656
+
657
+ {
658
+ name: "bundle_list_concatenation",
659
+ description: "list + list returns a concatenated list in the bundled baselib",
660
+ run: function () {
661
+ var repl = RS.web_repl();
662
+ var js = bundle_compile(repl, [
663
+ "a = [1, 2]",
664
+ "b = [3, 4]",
665
+ "c = a + b",
666
+ "assrt.deepEqual(c, [1, 2, 3, 4])",
667
+ "assrt.deepEqual(a, [1, 2])",
668
+ "assrt.deepEqual(b, [3, 4])",
669
+ "# iadd extends in-place",
670
+ "a += [5]",
671
+ "assrt.deepEqual(a, [1, 2, 5])",
672
+ "# numbers still work",
673
+ "assrt.equal(1 + 2, 3)",
674
+ "# strings still work",
675
+ "assrt.equal('foo' + 'bar', 'foobar')",
676
+ ].join("\n"));
677
+ run_js(js);
678
+ },
679
+ },
680
+
681
+ // ── React stub tests ─────────────────────────────────────────────────────
682
+ // These tests require a React mock in the vm context because the compiled
683
+ // react.pyj module initialises with `React.*` references at load time.
684
+
685
+ {
686
+ name: "bundle_react_stub_memo",
687
+ description: "web-repl React stub: memo() returns its argument (identity wrapper)",
688
+ run: function () {
689
+ var repl = RS.web_repl();
690
+ var js = bundle_compile(repl, [
691
+ "from react import memo",
692
+ "def MyComp(props): return props.x",
693
+ "Memoised = memo(MyComp)",
694
+ "assrt.equal(Memoised, MyComp)",
695
+ ].join("\n"));
696
+ run_js_with_react(js);
697
+ },
698
+ },
699
+
700
+ {
701
+ name: "bundle_react_stub_usestate",
702
+ description: "web-repl React stub: useState returns [initialValue, setter]",
703
+ run: function () {
704
+ var repl = RS.web_repl();
705
+ var js = bundle_compile(repl, [
706
+ "from react import useState",
707
+ "state, setState = useState(42)",
708
+ "assrt.equal(state, 42)",
709
+ "assrt.equal(jstype(setState), 'function')",
710
+ ].join("\n"));
711
+ run_js_with_react(js);
712
+ },
713
+ },
714
+
715
+ {
716
+ name: "bundle_react_stub_useeffect",
717
+ description: "web-repl React stub: useEffect calls its callback immediately",
718
+ run: function () {
719
+ var repl = RS.web_repl();
720
+ var js = bundle_compile(repl, [
721
+ "from react import useEffect",
722
+ "ran = [False]",
723
+ "def effect(): ran[0] = True",
724
+ "useEffect(effect, [])",
725
+ "assrt.ok(ran[0])",
726
+ ].join("\n"));
727
+ run_js_with_react(js);
728
+ },
729
+ },
730
+
731
+ {
732
+ name: "bundle_react_stub_usememo",
733
+ description: "web-repl React stub: useMemo returns the computed value",
734
+ run: function () {
735
+ var repl = RS.web_repl();
736
+ var js = bundle_compile(repl, [
737
+ "from react import useMemo",
738
+ "result = useMemo(def(): return 6 * 7;, [])",
739
+ "assrt.equal(result, 42)",
740
+ ].join("\n"));
741
+ run_js_with_react(js);
742
+ },
743
+ },
744
+
745
+ {
746
+ name: "bundle_react_stub_useref",
747
+ description: "web-repl React stub: useRef returns {current: initialValue}",
748
+ run: function () {
749
+ var repl = RS.web_repl();
750
+ var js = bundle_compile(repl, [
751
+ "from react import useRef",
752
+ "ref = useRef(None)",
753
+ "assrt.equal(ref.current, None)",
754
+ "ref.current = 'hello'",
755
+ "assrt.equal(ref.current, 'hello')",
756
+ ].join("\n"));
757
+ run_js_with_react(js);
758
+ },
759
+ },
760
+
761
+ {
762
+ name: "bundle_react_stub_usereducer",
763
+ description: "web-repl React stub: useReducer returns [initialState, dispatch]",
764
+ run: function () {
765
+ var repl = RS.web_repl();
766
+ var js = bundle_compile(repl, [
767
+ "from react import useReducer",
768
+ "def reducer(state, action):",
769
+ " if action == 'inc': return state + 1",
770
+ " return state",
771
+ "state, dispatch = useReducer(reducer, 0)",
772
+ "assrt.equal(state, 0)",
773
+ "assrt.equal(jstype(dispatch), 'function')",
774
+ ].join("\n"));
775
+ run_js_with_react(js);
776
+ },
777
+ },
778
+
779
+ {
780
+ name: "bundle_react_stub_createcontext",
781
+ description: "web-repl React stub: createContext returns a context with default value",
782
+ run: function () {
783
+ var repl = RS.web_repl();
784
+ var js = bundle_compile(repl, [
785
+ "from react import createContext, useContext",
786
+ "ThemeCtx = createContext('dark')",
787
+ "theme = useContext(ThemeCtx)",
788
+ "assrt.equal(theme, 'dark')",
789
+ ].join("\n"));
790
+ run_js_with_react(js);
791
+ },
792
+ },
793
+
794
+ {
795
+ name: "bundle_react_stub_forwardref",
796
+ description: "web-repl React stub: forwardRef wraps the render function",
797
+ run: function () {
798
+ var repl = RS.web_repl();
799
+ var js = bundle_compile(repl, [
800
+ "from react import forwardRef",
801
+ "def render(props, ref): return props.x",
802
+ "FancyInput = forwardRef(render)",
803
+ "assrt.equal(jstype(FancyInput), 'function')",
804
+ "assrt.equal(FancyInput({'x': 99}), 99)",
805
+ ].join("\n"));
806
+ run_js_with_react(js);
807
+ },
808
+ },
809
+
810
+ {
811
+ name: "bundle_react_stub_jsx_and_memo",
812
+ description: "web-repl React stub: JSX component wrapped with memo compiles and runs",
813
+ run: function () {
814
+ var repl = RS.web_repl();
815
+ var js = bundle_compile(repl, [
816
+ "from __python__ import jsx",
817
+ "from react import useState, memo",
818
+ "def Counter(props):",
819
+ " count, setCount = useState(props.initial or 0)",
820
+ " return <span>{count}</span>",
821
+ "MemoCounter = memo(Counter)",
822
+ "assrt.equal(jstype(MemoCounter), 'function')",
823
+ "el = MemoCounter({'initial': 7})",
824
+ "assrt.equal(el.type, 'span')",
825
+ ].join("\n"));
826
+ run_js_with_react(js);
827
+ },
828
+ },
829
+
830
+ // ── __import__() ─────────────────────────────────────────────────────
831
+
832
+ {
833
+ name: "bundle___import__-basic",
834
+ description: "__import__(name) returns a stdlib module reference in the web-repl bundle",
835
+ run: function () {
836
+ var repl = RS.web_repl();
837
+ var js = bundle_compile(repl, [
838
+ "from collections import Counter",
839
+ "m = __import__('collections')",
840
+ // m.Counter should be the same object as the statically-imported Counter
841
+ "assrt.ok(m.Counter is Counter)",
842
+ "c = m.Counter('aabb')",
843
+ "top = c.most_common(1)",
844
+ "assrt.equal(top[0][0], 'a')",
845
+ "assrt.equal(top[0][1], 2)",
846
+ ].join("\n"));
847
+ run_js(js);
848
+ },
849
+ },
850
+
851
+ {
852
+ name: "bundle___import__-fromlist",
853
+ description: "__import__ with fromlist returns the exact named module",
854
+ run: function () {
855
+ var repl = RS.web_repl();
856
+ var js = bundle_compile(repl, [
857
+ "from collections import deque",
858
+ "m = __import__('collections', None, None, ['deque'])",
859
+ "d = m.deque([1, 2, 3])",
860
+ "assrt.equal(len(d), 3)",
861
+ "assrt.equal(d.popleft(), 1)",
862
+ ].join("\n"));
863
+ run_js(js);
864
+ },
865
+ },
866
+
867
+ {
868
+ name: "bundle___import__-error",
869
+ description: "__import__ raises ModuleNotFoundError for unknown module in web-repl",
870
+ run: function () {
871
+ var repl = RS.web_repl();
872
+ var js = bundle_compile(repl, [
873
+ "from collections import Counter",
874
+ "caught = False",
875
+ "try:",
876
+ " __import__('no_such_module')",
877
+ "except ModuleNotFoundError as e:",
878
+ " caught = True",
879
+ "assrt.ok(caught)",
880
+ ].join("\n"));
881
+ run_js(js);
882
+ },
883
+ },
884
+
448
885
  ];
449
886
 
450
887
  // ---------------------------------------------------------------------------
@@ -14,7 +14,7 @@ var path = require("path");
14
14
 
15
15
  var SRC_DIR = path.join(__dirname, "..", "src", "monaco-language-service");
16
16
  var COMPILER_JS = path.join(__dirname, "..", "web-repl", "rapydscript.js");
17
- var DEFAULT_OUT = path.join(__dirname, "..", "web-repl", "language-service.js");
17
+ var DEFAULT_OUT = path.join(__dirname, "..", "language-service", "index.js");
18
18
 
19
19
  // Parse --out flag
20
20
  var out_path = DEFAULT_OUT;
@@ -124,7 +124,7 @@ var chunks = [
124
124
  "// language-service.js — RapydScript Monaco Language Service",
125
125
  "// Auto-generated by tools/build-language-service.js — do not edit directly.",
126
126
  "// Source: src/monaco-language-service/ + web-repl/rapydscript.js (embedded)",
127
- "// Usage: import { registerRapydScript } from './language-service.js';",
127
+ "// Usage: import { registerRapydScript } from 'rapydscript-ns/language-service';",
128
128
  "// No external compiler bundle needed — the compiler is bundled inside.",
129
129
  "",
130
130
  compiler_chunk,