rapydscript-ns 0.8.3 → 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 (116) 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 +8 -0
  5. package/HACKING.md +103 -103
  6. package/LICENSE +24 -24
  7. package/PYTHON_DIFFERENCES_REPORT.md +2 -2
  8. package/PYTHON_FEATURE_COVERAGE.md +13 -13
  9. package/README.md +670 -6
  10. package/TODO.md +5 -6
  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 +155 -6
  17. package/package.json +1 -1
  18. package/publish.py +37 -37
  19. package/release/baselib-plain-pretty.js +2006 -229
  20. package/release/baselib-plain-ugly.js +70 -3
  21. package/release/compiler.js +11554 -3870
  22. package/release/signatures.json +31 -29
  23. package/session.vim +4 -4
  24. package/setup.cfg +2 -2
  25. package/src/ast.pyj +93 -1
  26. package/src/baselib-builtins.pyj +22 -1
  27. package/src/baselib-containers.pyj +99 -0
  28. package/src/baselib-errors.pyj +44 -0
  29. package/src/baselib-internal.pyj +94 -4
  30. package/src/baselib-itertools.pyj +97 -97
  31. package/src/baselib-str.pyj +24 -0
  32. package/src/compiler.pyj +36 -36
  33. package/src/errors.pyj +30 -30
  34. package/src/lib/aes.pyj +646 -646
  35. package/src/lib/copy.pyj +120 -0
  36. package/src/lib/elementmaker.pyj +83 -83
  37. package/src/lib/encodings.pyj +126 -126
  38. package/src/lib/gettext.pyj +569 -569
  39. package/src/lib/itertools.pyj +580 -580
  40. package/src/lib/math.pyj +193 -193
  41. package/src/lib/operator.pyj +11 -11
  42. package/src/lib/pythonize.pyj +20 -20
  43. package/src/lib/random.pyj +118 -118
  44. package/src/lib/re.pyj +470 -470
  45. package/src/lib/react.pyj +74 -0
  46. package/src/lib/traceback.pyj +63 -63
  47. package/src/lib/uuid.pyj +77 -77
  48. package/src/monaco-language-service/builtins.js +5 -0
  49. package/src/monaco-language-service/diagnostics.js +25 -3
  50. package/src/monaco-language-service/dts.js +550 -550
  51. package/src/output/classes.pyj +108 -8
  52. package/src/output/codegen.pyj +16 -2
  53. package/src/output/comments.pyj +45 -45
  54. package/src/output/exceptions.pyj +201 -105
  55. package/src/output/functions.pyj +9 -0
  56. package/src/output/jsx.pyj +164 -0
  57. package/src/output/literals.pyj +28 -2
  58. package/src/output/modules.pyj +1 -1
  59. package/src/output/operators.pyj +8 -2
  60. package/src/output/statements.pyj +2 -2
  61. package/src/output/stream.pyj +1 -0
  62. package/src/output/treeshake.pyj +182 -182
  63. package/src/output/utils.pyj +72 -72
  64. package/src/parse.pyj +417 -113
  65. package/src/string_interpolation.pyj +72 -72
  66. package/src/tokenizer.pyj +29 -0
  67. package/src/unicode_aliases.pyj +576 -576
  68. package/src/utils.pyj +192 -192
  69. package/test/_import_one.pyj +37 -37
  70. package/test/_import_two/__init__.pyj +11 -11
  71. package/test/_import_two/level2/deep.pyj +4 -4
  72. package/test/_import_two/other.pyj +6 -6
  73. package/test/_import_two/sub.pyj +13 -13
  74. package/test/aes_vectors.pyj +421 -421
  75. package/test/annotations.pyj +80 -80
  76. package/test/decorators.pyj +77 -77
  77. package/test/docstrings.pyj +39 -39
  78. package/test/elementmaker_test.pyj +45 -45
  79. package/test/functions.pyj +151 -151
  80. package/test/generators.pyj +41 -41
  81. package/test/generic.pyj +370 -370
  82. package/test/imports.pyj +72 -72
  83. package/test/internationalization.pyj +73 -73
  84. package/test/lint.pyj +164 -164
  85. package/test/loops.pyj +85 -85
  86. package/test/numpy.pyj +734 -734
  87. package/test/omit_function_metadata.pyj +20 -20
  88. package/test/python_features.pyj +19 -6
  89. package/test/regexp.pyj +55 -55
  90. package/test/repl.pyj +121 -121
  91. package/test/scoped_flags.pyj +76 -76
  92. package/test/unit/index.js +2177 -64
  93. package/test/unit/language-service-dts.js +543 -543
  94. package/test/unit/language-service-hover.js +455 -455
  95. package/test/unit/language-service.js +590 -4
  96. package/test/unit/web-repl.js +303 -0
  97. package/tools/cli.js +547 -547
  98. package/tools/compile.js +219 -219
  99. package/tools/completer.js +131 -131
  100. package/tools/embedded_compiler.js +251 -251
  101. package/tools/gettext.js +185 -185
  102. package/tools/ini.js +65 -65
  103. package/tools/msgfmt.js +187 -187
  104. package/tools/repl.js +223 -223
  105. package/tools/test.js +118 -118
  106. package/tools/utils.js +128 -128
  107. package/tools/web_repl.js +95 -95
  108. package/try +41 -41
  109. package/web-repl/env.js +196 -74
  110. package/web-repl/index.html +163 -163
  111. package/web-repl/main.js +252 -254
  112. package/web-repl/prism.css +139 -139
  113. package/web-repl/prism.js +113 -113
  114. package/web-repl/rapydscript.js +224 -102
  115. package/web-repl/sha1.js +25 -25
  116. package/hack_demo.pyj +0 -112
@@ -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
  // ---------------------------------------------------------------------------
@@ -555,6 +619,41 @@ var TESTS = [
555
619
  },
556
620
  },
557
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
+
558
657
  {
559
658
  name: "bundle_list_concatenation",
560
659
  description: "list + list returns a concatenated list in the bundled baselib",
@@ -579,6 +678,210 @@ var TESTS = [
579
678
  },
580
679
  },
581
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
+
582
885
  ];
583
886
 
584
887
  // ---------------------------------------------------------------------------