rapydscript-ns 0.9.3 → 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 (98) 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 +9 -0
  5. package/HACKING.md +103 -103
  6. package/LICENSE +24 -24
  7. package/PYTHON_GAPS.md +48 -116
  8. package/README.md +35 -15
  9. package/TODO.md +1 -26
  10. package/add-toc-to-readme +2 -2
  11. package/bin/export +75 -75
  12. package/bin/rapydscript +0 -0
  13. package/bin/web-repl-export +102 -102
  14. package/build +2 -2
  15. package/language-service/index.js +9 -7
  16. package/package.json +1 -1
  17. package/publish.py +37 -37
  18. package/session.vim +4 -4
  19. package/setup.cfg +2 -2
  20. package/src/ast.pyj +6 -0
  21. package/src/baselib-containers.pyj +23 -1
  22. package/src/baselib-str.pyj +13 -2
  23. package/src/compiler.pyj +36 -36
  24. package/src/errors.pyj +30 -30
  25. package/src/lib/aes.pyj +646 -646
  26. package/src/lib/collections.pyj +227 -3
  27. package/src/lib/copy.pyj +120 -120
  28. package/src/lib/elementmaker.pyj +83 -83
  29. package/src/lib/encodings.pyj +126 -126
  30. package/src/lib/gettext.pyj +569 -569
  31. package/src/lib/itertools.pyj +580 -580
  32. package/src/lib/math.pyj +193 -193
  33. package/src/lib/operator.pyj +11 -11
  34. package/src/lib/pprint.pyj +455 -0
  35. package/src/lib/random.pyj +118 -118
  36. package/src/lib/react.pyj +74 -74
  37. package/src/lib/statistics.pyj +0 -0
  38. package/src/lib/traceback.pyj +63 -63
  39. package/src/lib/uuid.pyj +77 -77
  40. package/src/monaco-language-service/diagnostics.js +2 -2
  41. package/src/monaco-language-service/dts.js +550 -550
  42. package/src/output/codegen.pyj +4 -1
  43. package/src/output/comments.pyj +45 -45
  44. package/src/output/exceptions.pyj +201 -201
  45. package/src/output/jsx.pyj +164 -164
  46. package/src/output/treeshake.pyj +182 -182
  47. package/src/output/utils.pyj +72 -72
  48. package/src/parse.pyj +28 -7
  49. package/src/string_interpolation.pyj +72 -72
  50. package/src/tokenizer.pyj +18 -2
  51. package/src/unicode_aliases.pyj +576 -576
  52. package/src/utils.pyj +192 -192
  53. package/test/_import_one.pyj +37 -37
  54. package/test/_import_two/__init__.pyj +11 -11
  55. package/test/_import_two/level2/deep.pyj +4 -4
  56. package/test/_import_two/other.pyj +6 -6
  57. package/test/_import_two/sub.pyj +13 -13
  58. package/test/aes_vectors.pyj +421 -421
  59. package/test/annotations.pyj +80 -80
  60. package/test/baselib.pyj +23 -0
  61. package/test/chainmap.pyj +185 -0
  62. package/test/decorators.pyj +77 -77
  63. package/test/docstrings.pyj +39 -39
  64. package/test/elementmaker_test.pyj +45 -45
  65. package/test/functions.pyj +151 -151
  66. package/test/generators.pyj +41 -41
  67. package/test/generic.pyj +370 -370
  68. package/test/internationalization.pyj +73 -73
  69. package/test/lint.pyj +164 -164
  70. package/test/loops.pyj +85 -85
  71. package/test/numpy.pyj +734 -734
  72. package/test/pprint.pyj +232 -0
  73. package/test/repl.pyj +121 -121
  74. package/test/scoped_flags.pyj +76 -76
  75. package/test/statistics.pyj +224 -0
  76. package/test/unit/index.js +80 -0
  77. package/test/unit/language-service-completions.js +2 -0
  78. package/test/unit/language-service-dts.js +543 -543
  79. package/test/unit/language-service-hover.js +455 -455
  80. package/test/unit/language-service.js +63 -2
  81. package/test/unit/web-repl.js +323 -0
  82. package/tools/compiler.d.ts +367 -367
  83. package/tools/completer.js +131 -131
  84. package/tools/export.js +4 -2
  85. package/tools/gettext.js +185 -185
  86. package/tools/ini.js +65 -65
  87. package/tools/msgfmt.js +187 -187
  88. package/tools/repl.js +223 -223
  89. package/tools/test.js +118 -118
  90. package/tools/utils.js +128 -128
  91. package/tools/web_repl.js +95 -95
  92. package/try +41 -41
  93. package/web-repl/env.js +196 -196
  94. package/web-repl/index.html +163 -163
  95. package/web-repl/prism.css +139 -139
  96. package/web-repl/prism.js +113 -113
  97. package/web-repl/rapydscript.js +228 -226
  98. package/web-repl/sha1.js +25 -25
package/.agignore CHANGED
@@ -1 +1 @@
1
- lib/*
1
+ lib/*
@@ -1,38 +1,38 @@
1
- name: CI
2
- on: [push, pull_request]
3
- env:
4
- CI: 'true'
5
-
6
- jobs:
7
- test:
8
- name: Test on ${{ matrix.os }} LANG ${{ matrix.lang }}
9
- runs-on: ${{ matrix.os }}
10
- env:
11
- LANG: ${{ matrix.lang }}
12
- LC_ALL: ${{ matrix.lang }}
13
- strategy:
14
- matrix:
15
- include:
16
- - { os: ubuntu-latest, lang: en_US.UTF-8 }
17
- - { os: ubuntu-latest, lang: de_DE.UTF-8}
18
- - { os: ubuntu-latest, lang: hi_IN.UTF-8 }
19
-
20
- - { os: macos-latest, lang: en_US.UTF-8 }
21
- - { os: windows-latest, lang: en_US.UTF-8 }
22
-
23
- steps:
24
- - name: Checkout source code
25
- uses: actions/checkout@master
26
- with:
27
- fetch-depth: 10
28
-
29
- - name: Set up Node ${{ matrix.node }}
30
- uses: actions/setup-node@master
31
-
32
- - name: Install deps
33
- run:
34
- npm install --no-optional
35
-
36
- - name: Test
37
- run:
38
- npm test
1
+ name: CI
2
+ on: [push, pull_request]
3
+ env:
4
+ CI: 'true'
5
+
6
+ jobs:
7
+ test:
8
+ name: Test on ${{ matrix.os }} LANG ${{ matrix.lang }}
9
+ runs-on: ${{ matrix.os }}
10
+ env:
11
+ LANG: ${{ matrix.lang }}
12
+ LC_ALL: ${{ matrix.lang }}
13
+ strategy:
14
+ matrix:
15
+ include:
16
+ - { os: ubuntu-latest, lang: en_US.UTF-8 }
17
+ - { os: ubuntu-latest, lang: de_DE.UTF-8}
18
+ - { os: ubuntu-latest, lang: hi_IN.UTF-8 }
19
+
20
+ - { os: macos-latest, lang: en_US.UTF-8 }
21
+ - { os: windows-latest, lang: en_US.UTF-8 }
22
+
23
+ steps:
24
+ - name: Checkout source code
25
+ uses: actions/checkout@master
26
+ with:
27
+ fetch-depth: 10
28
+
29
+ - name: Set up Node ${{ matrix.node }}
30
+ uses: actions/setup-node@master
31
+
32
+ - name: Install deps
33
+ run:
34
+ npm install --no-optional
35
+
36
+ - name: Test
37
+ run:
38
+ npm test
package/=template.pyj CHANGED
@@ -1,5 +1,5 @@
1
- # vim:fileencoding=utf-8
2
- # License: BSD Copyright: %YEAR%, %USER% <%MAIL%>
3
- from __python__ import hash_literals
4
-
5
- %HERE%
1
+ # vim:fileencoding=utf-8
2
+ # License: BSD Copyright: %YEAR%, %USER% <%MAIL%>
3
+ from __python__ import hash_literals
4
+
5
+ %HERE%
package/CHANGELOG.md CHANGED
@@ -1,3 +1,12 @@
1
+ version 0.9.4
2
+ =======================
3
+ * Added the `statistics` standard library module (`mean`, `fmean`, `median`, `median_low`, `median_high`, `median_grouped`, `mode`, `multimode`, `stdev`, `pstdev`, `variance`, `pvariance`, `harmonic_mean`, `geometric_mean`, `quantiles`, `covariance`, `correlation`, `linear_regression`, `NormalDist`)
4
+ * Added the `pprint` standard library module (`pprint`, `pformat`, `PrettyPrinter`, `isreadable`, `isrecursive`, `saferepr`)
5
+ * Added `ChainMap` to the `collections` standard library module
6
+ * Added support for `bigint` literals and the `bigint()` builtin
7
+ * Fix: Added the `type` builtin to global scope
8
+ * Fix: Performance problem during long editor sessions in the language service
9
+
1
10
  version 0.9.3
2
11
  =======================
3
12
  * Added the `bisect` standard library module (`bisect_left`, `bisect_right`, `bisect`, `insort_left`, `insort_right`, `insort`, optional `key` parameter)
package/HACKING.md CHANGED
@@ -1,103 +1,103 @@
1
- Hacking the RapydScript compiler
2
- =================================
3
-
4
- The RapydScript compiler is written in RapydScript itself and uses the
5
- RapydScript import system to modularize its code. The compiler source code is
6
- in the `src` directory. The compiled compiler is by default in the `release`
7
- directory.
8
-
9
- In order to start hacking on the compiler, run the command
10
-
11
- ```
12
- bin/rapydscript self --complete --test
13
- ```
14
-
15
- This will generate a build of the compiler in the `dev` directory. Now, the
16
- rapydscript command will automatically use this build, rather than the one in
17
- release. If you want to go back to the release build, simply delete the `dev`
18
- directory.
19
-
20
-
21
- Code organization
22
- -------------------
23
-
24
- The way the compiler works, given some RapydScript source code:
25
-
26
- * The source code is lexed into a stream of tokens (`src/tokenzier.pyj`)
27
-
28
- * The tokens are parsed into a Abstract Syntax Tree (`src/parse.pyj and src/ast.pyj`)
29
-
30
- * During parsing any import statement are resolved (this is different from
31
- python, where imports happen at run-time, not compile time).
32
-
33
- * The Abstract Syntax Tree is transformed into the output JavaScript (`src/output/*.pyj`)
34
-
35
- * Various bits of functionality in RapydScript depend upon the *Base Library*
36
- (`src/baselib*.pyj`). This includes things like the basic container types
37
- (list/set/dict) string functions such as `str.format()`, etc. The baselib
38
- is automatically inserted into the start of the output JavaScript.
39
-
40
- The RapydScript standard library can be found in `src/lib`. The various tools,
41
- such as the linter, gettext support, the REPL, etc. are in the `tools`
42
- directory.
43
-
44
- Tests
45
- --------
46
-
47
- The tests are in the test directory and can be run using the command:
48
- ```
49
- rapydscript test
50
- ```
51
-
52
- You can run individual test files by providing the name of the file, as
53
-
54
- ```
55
- rapydscript test classes
56
- ```
57
-
58
- Modifying the compiler
59
- -------------------------
60
-
61
- Edit the files in the `src` directory to make your changes, then use the
62
- `./try` script to test them. This script will compile an updated version of
63
- the compiler with your changes, if any, and use it to run the snippet of code
64
- you pass to it.
65
-
66
- For example:
67
-
68
- ```
69
- ./try 'print("Hello world")'
70
- ```
71
-
72
- will compile `print ("Hello world")` and show you the output on stdout. You can
73
- tell it to omit the baselib, so you can focus on the output, with the `-m`
74
- switch, like this:
75
-
76
- ```
77
- ./try -m 'print("Hello world")'
78
- ```
79
-
80
- You can also have it not print out the JavaScript, instead directly executing the output
81
- JavaScript with the `-x` switch, like this
82
-
83
- ```
84
- ./try -x 'print("Hello world")'
85
- ```
86
-
87
- If you want to test longer sections of code, you can use the `-f` switch to
88
- pass in the path to a RapydScript file to compile, like this:
89
-
90
- ```
91
- ./try -f myfile.pyj
92
- ```
93
-
94
- Once you are happy with your changes, you can build the compiler and run the
95
- test suite, all with a single command:
96
-
97
- ```
98
- ./build
99
- ```
100
-
101
- This will build the compiler with the updated version of itself and then run
102
- the test suite. If all test pass you can commit your changes and send a pull
103
- request :)
1
+ Hacking the RapydScript compiler
2
+ =================================
3
+
4
+ The RapydScript compiler is written in RapydScript itself and uses the
5
+ RapydScript import system to modularize its code. The compiler source code is
6
+ in the `src` directory. The compiled compiler is by default in the `release`
7
+ directory.
8
+
9
+ In order to start hacking on the compiler, run the command
10
+
11
+ ```
12
+ bin/rapydscript self --complete --test
13
+ ```
14
+
15
+ This will generate a build of the compiler in the `dev` directory. Now, the
16
+ rapydscript command will automatically use this build, rather than the one in
17
+ release. If you want to go back to the release build, simply delete the `dev`
18
+ directory.
19
+
20
+
21
+ Code organization
22
+ -------------------
23
+
24
+ The way the compiler works, given some RapydScript source code:
25
+
26
+ * The source code is lexed into a stream of tokens (`src/tokenzier.pyj`)
27
+
28
+ * The tokens are parsed into a Abstract Syntax Tree (`src/parse.pyj and src/ast.pyj`)
29
+
30
+ * During parsing any import statement are resolved (this is different from
31
+ python, where imports happen at run-time, not compile time).
32
+
33
+ * The Abstract Syntax Tree is transformed into the output JavaScript (`src/output/*.pyj`)
34
+
35
+ * Various bits of functionality in RapydScript depend upon the *Base Library*
36
+ (`src/baselib*.pyj`). This includes things like the basic container types
37
+ (list/set/dict) string functions such as `str.format()`, etc. The baselib
38
+ is automatically inserted into the start of the output JavaScript.
39
+
40
+ The RapydScript standard library can be found in `src/lib`. The various tools,
41
+ such as the linter, gettext support, the REPL, etc. are in the `tools`
42
+ directory.
43
+
44
+ Tests
45
+ --------
46
+
47
+ The tests are in the test directory and can be run using the command:
48
+ ```
49
+ rapydscript test
50
+ ```
51
+
52
+ You can run individual test files by providing the name of the file, as
53
+
54
+ ```
55
+ rapydscript test classes
56
+ ```
57
+
58
+ Modifying the compiler
59
+ -------------------------
60
+
61
+ Edit the files in the `src` directory to make your changes, then use the
62
+ `./try` script to test them. This script will compile an updated version of
63
+ the compiler with your changes, if any, and use it to run the snippet of code
64
+ you pass to it.
65
+
66
+ For example:
67
+
68
+ ```
69
+ ./try 'print("Hello world")'
70
+ ```
71
+
72
+ will compile `print ("Hello world")` and show you the output on stdout. You can
73
+ tell it to omit the baselib, so you can focus on the output, with the `-m`
74
+ switch, like this:
75
+
76
+ ```
77
+ ./try -m 'print("Hello world")'
78
+ ```
79
+
80
+ You can also have it not print out the JavaScript, instead directly executing the output
81
+ JavaScript with the `-x` switch, like this
82
+
83
+ ```
84
+ ./try -x 'print("Hello world")'
85
+ ```
86
+
87
+ If you want to test longer sections of code, you can use the `-f` switch to
88
+ pass in the path to a RapydScript file to compile, like this:
89
+
90
+ ```
91
+ ./try -f myfile.pyj
92
+ ```
93
+
94
+ Once you are happy with your changes, you can build the compiler and run the
95
+ test suite, all with a single command:
96
+
97
+ ```
98
+ ./build
99
+ ```
100
+
101
+ This will build the compiler with the updated version of itself and then run
102
+ the test suite. If all test pass you can commit your changes and send a pull
103
+ request :)
package/LICENSE CHANGED
@@ -1,24 +1,24 @@
1
- Copyright (c) 2015-, Kovid Goyal <kovid@kovidgoyal.net>
2
- Copyright (c) 2013-2014, Alexander Tsepkov <atsepkov@pyjeon.com>
3
- All rights reserved.
4
-
5
- Redistribution and use in source and binary forms, with or without
6
- modification, are permitted provided that the following conditions are met:
7
-
8
- * Redistributions of source code must retain the above copyright notice, this
9
- list of conditions and the following disclaimer.
10
-
11
- * Redistributions in binary form must reproduce the above copyright notice,
12
- this list of conditions and the following disclaimer in the documentation
13
- and/or other materials provided with the distribution.
14
-
15
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19
- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21
- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22
- CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23
- OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1
+ Copyright (c) 2015-, Kovid Goyal <kovid@kovidgoyal.net>
2
+ Copyright (c) 2013-2014, Alexander Tsepkov <atsepkov@pyjeon.com>
3
+ All rights reserved.
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ * Redistributions of source code must retain the above copyright notice, this
9
+ list of conditions and the following disclaimer.
10
+
11
+ * Redistributions in binary form must reproduce the above copyright notice,
12
+ this list of conditions and the following disclaimer in the documentation
13
+ and/or other materials provided with the distribution.
14
+
15
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package/PYTHON_GAPS.md CHANGED
@@ -5,6 +5,9 @@ or behave differently in RapydScript-NS, with a focus on what is relevant and us
5
5
  browser context. Server-side features (file I/O, subprocesses, sockets, threading, etc.)
6
6
  are excluded as they do not apply.
7
7
 
8
+ Items that are fully supported — even if only behind a flag — are not listed here. See the
9
+ README for the full feature and module support tables.
10
+
8
11
  ---
9
12
 
10
13
  ## 1. Silent Behavioral Differences (Gotchas)
@@ -12,23 +15,7 @@ are excluded as they do not apply.
12
15
  These features exist but behave differently from Python in ways that will silently produce
13
16
  wrong results — no error is raised.
14
17
 
15
- ### 1.1 `%` Modulo on Negative Numbers *(partially resolved)*
16
-
17
- **Python:** `%` always returns a non-negative result (true modulo).
18
- ```python
19
- -7 % 3 # → 2 (Python)
20
- -7 % 3 # → -1 (RapydScript default — JS remainder semantics)
21
- ```
22
- **Status:** Fixed when using `from __python__ import overload_operators` or
23
- `from __python__ import python_modulo`. In bare mode (no flags) the JS remainder semantics
24
- still apply.
25
-
26
- **Impact:** Any algorithm relying on modular arithmetic (wrapping, circular indexing) may
27
- produce wrong results in code that does not use the Python operator flags.
28
-
29
- ---
30
-
31
- ### 1.2 `is` / `is not` — Identity vs. Equality
18
+ ### 1.1 `is` / `is not` Identity vs. Equality
32
19
 
33
20
  **Python:** `is` tests object identity (pointer comparison).
34
21
  **RapydScript:** `is` compiles to `===` (strict equality), so `x is y` is true whenever
@@ -48,43 +35,7 @@ The recommended pattern — using a unique sentinel object — works correctly.
48
35
 
49
36
  ---
50
37
 
51
- ### 1.3 Function Arguments: `TypeError` on Wrong Count *(opt-in, not default)*
52
-
53
- **Python:** Too few or too many positional arguments raises `TypeError` at call time.
54
- **RapydScript default:** Extra args are silently discarded; missing args become `undefined`.
55
-
56
- ```python
57
- def f(a, b):
58
- return a + b
59
-
60
- f(1, 2, 3) # Python: TypeError. RapydScript default: silently returns 3
61
- f(1) # Python: TypeError. RapydScript default: returns NaN (1 + undefined)
62
- ```
63
- **Status:** Argument count and type-annotation enforcement is now available via the
64
- `type_enforce` flag on function definitions (emits runtime checks). Not enabled by default
65
- because it adds overhead to every call. Developers writing library code with strict APIs
66
- should opt in.
67
-
68
- ---
69
-
70
- ### 1.4 Positional-Only and Keyword-Only Parameters Not Enforced
71
-
72
- **Python:** Positional-only params (`/`) cannot be passed by keyword; keyword-only params
73
- (`*`) cannot be passed positionally. Both raise `TypeError` on violations.
74
- **RapydScript:** Violations are silently discarded — the param gets `undefined` with no error.
75
-
76
- ```python
77
- def f(a, b, /, *, c):
78
- return a + b + c
79
-
80
- f(1, b=2, c=3) # Python: TypeError (b is positional-only)
81
- # RapydScript: b silently becomes undefined, a=1, c=3
82
- ```
83
- **Impact:** API design contracts expressed via param ordering are not enforced.
84
-
85
- ---
86
-
87
- ### 1.5 String Encoding — UTF-16 Surrogate Pairs
38
+ ### 1.2 String Encoding UTF-16 Surrogate Pairs
88
39
 
89
40
  **Python:** Strings are sequences of Unicode code points (full 21-bit range).
90
41
  **RapydScript:** Strings are JS strings — UTF-16. Emoji and other non-BMP characters
@@ -103,7 +54,7 @@ produce wrong lengths or corrupt characters when sliced.
103
54
 
104
55
  ---
105
56
 
106
- ### 1.6 `global` Scoping in Nested Functions
57
+ ### 1.3 `global` Scoping in Nested Functions
107
58
 
108
59
  **Python:** `global x` inside a nested function forces `x` to refer to the module-level
109
60
  variable, bypassing any intermediate closure scopes.
@@ -115,7 +66,7 @@ scope silently.
115
66
 
116
67
  ---
117
68
 
118
- ### 1.7 Numeric Dict Keys Are Coerced to Strings
69
+ ### 1.4 Numeric Dict Keys Are Coerced to Strings
119
70
 
120
71
  **Python:** `d = {}; d[1] = 'a'; d['1'] = 'b'; len(d) == 2` (integer and string keys distinct).
121
72
  **RapydScript:** The Python `dict` type (backed by ES6 `Map`) stores them distinctly, but
@@ -126,7 +77,7 @@ when interoperating with JS APIs that return plain objects.
126
77
 
127
78
  ---
128
79
 
129
- ### 1.8 `Exception.args` vs `.message`
80
+ ### 1.5 `Exception.args` vs `.message`
130
81
 
131
82
  **Python:** `Exception('msg').args == ('msg',)` and `.message` is not a standard attribute.
132
83
  **RapydScript:** `.message` is the primary attribute (JS `Error` convention). `.args` is
@@ -136,7 +87,7 @@ not populated as a tuple with the message.
136
87
 
137
88
  ---
138
89
 
139
- ### 1.9 Multiple Inheritance MRO
90
+ ### 1.6 Multiple Inheritance MRO
140
91
 
141
92
  **Python:** C3 linearization guarantees a deterministic and consistent method resolution order.
142
93
  **RapydScript:** Built on the JS prototype chain. In diamond inheritance or complex hierarchies
@@ -175,8 +126,10 @@ that timing is not guaranteed.
175
126
 
176
127
  ### 2.3 `locals()` Always Returns Empty Dict
177
128
 
178
- JavaScript provides no mechanism to introspect local variables at runtime. `locals()` always
179
- returns an empty dict. Python code that uses `locals()` for string template substitution
129
+ `vars()`, `locals()`, and `globals()` all exist as builtins. JavaScript provides no mechanism
130
+ to introspect local variables at runtime, so `locals()` always returns an empty dict.
131
+ `globals()` works on module-level/global state, and `vars(obj)` introspects the passed object.
132
+ Python code that uses `locals()` for string template substitution
180
133
  (e.g., `'{x}'.format(**locals())`) will break silently.
181
134
 
182
135
  ---
@@ -193,6 +146,8 @@ who rely on them (e.g., `from math import *`) must enumerate imports explicitly.
193
146
  ### 2.5 `asynccontextmanager` Not Available
194
147
 
195
148
  `contextlib.asynccontextmanager` is absent. Only synchronous `@contextmanager` is implemented.
149
+ `async with` itself is also not supported — async context managers need `.acquire()`/`.release()`
150
+ calls instead.
196
151
 
197
152
  ---
198
153
 
@@ -219,26 +174,35 @@ Python's `Ellipsis` singleton object. Code that stores `...` in containers or ch
219
174
 
220
175
  These are absent from `src/lib/` and have no substitute.
221
176
 
222
- ### 3.1 `decimal` Decimal Arithmetic
177
+ ### 3.1 `enum.IntEnum`, `IntFlag`, and `Flag`
223
178
 
224
- `Decimal` arithmetic avoids floating-point rounding errors. Essential for financial
225
- calculations in browser apps (e-commerce, budgeting tools). JS does not have a built-in
226
- equivalent; a pure-JS implementation would need to be compiled in.
179
+ The `enum` module provides `Enum` but not `IntEnum` (auto-comparable with integers),
180
+ `StrEnum` (Python 3.11+), `IntFlag`, or `Flag` (bitfield enums). These are common in protocol
181
+ implementations, permission systems, and state machines.
182
+
183
+ ```python
184
+ from enum import IntEnum
185
+ class Color(IntEnum):
186
+ RED = 1
187
+ GREEN = 2
188
+ Color.RED < Color.GREEN # True — comparison with int semantics
189
+ ```
227
190
 
228
191
  ---
229
192
 
230
- ### 3.2 `fractions` — Rational Arithmetic
193
+ ### 3.2 `hashlib` — Cryptographic Hashing
231
194
 
232
- `Fraction(numerator, denominator)` with full arithmetic. Useful for music theory apps,
233
- math tutoring tools, and any domain requiring exact rational computation.
195
+ `hashlib.sha256`, `hashlib.md5`, etc. The Web Crypto API provides `crypto.subtle.digest`
196
+ but its async/buffer-based interface is awkward. A thin `hashlib`-compatible wrapper over
197
+ `crypto.subtle` with a synchronous-friendly API (using the sync `crypto.getRandomValues`)
198
+ for non-cryptographic hashes would be valuable.
234
199
 
235
200
  ---
236
201
 
237
- ### 3.3 `statistics` — Statistical Functions
202
+ ### 3.3 `fractions` — Rational Arithmetic
238
203
 
239
- `mean`, `median`, `mode`, `stdev`, `variance`, `quantiles`. Very commonly needed in
240
- data-visualization browser apps. Currently `numpy` covers much of this but `statistics`
241
- is lighter-weight and doesn't require the full numpy import.
204
+ `Fraction(numerator, denominator)` with full arithmetic. Useful for music theory apps,
205
+ math tutoring tools, and any domain requiring exact rational computation.
242
206
 
243
207
  ---
244
208
 
@@ -249,42 +213,11 @@ for browser-based code editors, version comparison tools, and fuzzy matching UIs
249
213
 
250
214
  ---
251
215
 
252
- ### 3.5 `pprint` — Pretty Printing
253
-
254
- `pprint.pformat` / `pprint.pprint`. Primarily a debugging/REPL aid. Given the in-browser
255
- REPL in this project, implementing `pprint` would make output more readable.
256
-
257
- ---
258
-
259
- ### 3.6 `hashlib` — Cryptographic Hashing
260
-
261
- `hashlib.sha256`, `hashlib.md5`, etc. The Web Crypto API provides `crypto.subtle.digest`
262
- but its async/buffer-based interface is awkward. A thin `hashlib`-compatible wrapper over
263
- `crypto.subtle` with a synchronous-friendly API (using the sync `crypto.getRandomValues`)
264
- for non-cryptographic hashes would be valuable.
265
-
266
- ---
267
-
268
- ### 3.7 `enum.IntEnum` and `enum.Flag`
269
-
270
- The `enum` module provides `Enum` but not `IntEnum` (auto-comparable with integers),
271
- `StrEnum` (Python 3.11+), or `Flag` (bitfield enums). These are common in protocol
272
- implementations, permission systems, and state machines.
273
-
274
- ```python
275
- from enum import IntEnum
276
- class Color(IntEnum):
277
- RED = 1
278
- GREEN = 2
279
- Color.RED < Color.GREEN # True — comparison with int semantics
280
- ```
281
-
282
- ---
283
-
284
- ### 3.8 `collections.ChainMap`
216
+ ### 3.5 `decimal` — Decimal Arithmetic
285
217
 
286
- `ChainMap` provides a multi-level dict lookup (like layered config or scope chains) without
287
- copying. Not currently in `collections.pyj`.
218
+ `Decimal` arithmetic avoids floating-point rounding errors. Essential for financial
219
+ calculations in browser apps (e-commerce, budgeting tools). JS does not have a built-in
220
+ equivalent; a pure-JS implementation would need to be compiled in.
288
221
 
289
222
  ---
290
223
 
@@ -404,17 +337,16 @@ The `jstype()` builtin is the RS equivalent of JS's `typeof`.
404
337
 
405
338
  ## 5. Summary Priority Table
406
339
 
340
+ Priority weighs frequency-of-need, effort-to-implement, and whether a workaround exists.
341
+
407
342
  | Priority | Feature | Effort | Impact |
408
343
  |---|---|---|---|
409
- | High | `enum.IntEnum`, `Flag` | Medium | Protocol and permission modeling |
410
- | High | `statistics` module | Low | Data analysis without full numpy import |
411
- | Medium | `pprint` module | Low | REPL output quality |
412
- | Medium | `collections.ChainMap` | Low | Multi-level scope/config dicts |
413
- | Medium | f-string `f'{x=}'` debugging format | Low | Developer experience |
414
- | Medium | `__slots__` enforcement via `Proxy` | Medium | Memory + API documentation |
344
+ | High | `enum.IntEnum`, `IntFlag`, `Flag` | Medium | Protocol and permission modeling; bitfield enums |
345
+ | Medium | `__slots__` enforcement via `Proxy` | Medium | Memory and API documentation |
346
+ | Medium | `hashlib` shim over Web Crypto | Medium | Avoids verbatim Web Crypto calls in user code |
415
347
  | Medium | `fractions` module | Medium | Exact rational arithmetic |
416
- | Medium | `hashlib` shim over Web Crypto | Medium | Hashing without verbatim JS |
417
- | Low | `decimal` module | High | Financial calculations |
418
- | Low | `difflib` module | High | Text diff, fuzzy matching |
419
- | Low | `asynccontextmanager` | Medium | Async resource management |
348
+ | Medium | f-string `f'{x=}'` debugging format | Low | Developer experience |
349
+ | Low | `asynccontextmanager` + `async with` | Medium | Async resource management |
420
350
  | Low | `__del__` via `FinalizationRegistry` | Medium | Resource cleanup (best-effort) |
351
+ | Low | `difflib` module | High | Text diff, fuzzy matching |
352
+ | Low | `decimal` module | High | Financial calculations |