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.
- package/.agignore +1 -1
- package/.github/workflows/ci.yml +38 -38
- package/=template.pyj +5 -5
- package/CHANGELOG.md +8 -0
- package/HACKING.md +103 -103
- package/LICENSE +24 -24
- package/PYTHON_DIFFERENCES_REPORT.md +2 -2
- package/PYTHON_FEATURE_COVERAGE.md +13 -13
- package/README.md +670 -6
- package/TODO.md +5 -6
- package/add-toc-to-readme +2 -2
- package/bin/export +75 -75
- package/bin/rapydscript +70 -70
- package/bin/web-repl-export +102 -102
- package/build +2 -2
- package/language-service/index.js +155 -6
- package/package.json +1 -1
- package/publish.py +37 -37
- package/release/baselib-plain-pretty.js +2006 -229
- package/release/baselib-plain-ugly.js +70 -3
- package/release/compiler.js +11554 -3870
- package/release/signatures.json +31 -29
- package/session.vim +4 -4
- package/setup.cfg +2 -2
- package/src/ast.pyj +93 -1
- package/src/baselib-builtins.pyj +22 -1
- package/src/baselib-containers.pyj +99 -0
- package/src/baselib-errors.pyj +44 -0
- package/src/baselib-internal.pyj +94 -4
- package/src/baselib-itertools.pyj +97 -97
- package/src/baselib-str.pyj +24 -0
- package/src/compiler.pyj +36 -36
- package/src/errors.pyj +30 -30
- package/src/lib/aes.pyj +646 -646
- package/src/lib/copy.pyj +120 -0
- package/src/lib/elementmaker.pyj +83 -83
- package/src/lib/encodings.pyj +126 -126
- package/src/lib/gettext.pyj +569 -569
- package/src/lib/itertools.pyj +580 -580
- package/src/lib/math.pyj +193 -193
- package/src/lib/operator.pyj +11 -11
- package/src/lib/pythonize.pyj +20 -20
- package/src/lib/random.pyj +118 -118
- package/src/lib/re.pyj +470 -470
- package/src/lib/react.pyj +74 -0
- package/src/lib/traceback.pyj +63 -63
- package/src/lib/uuid.pyj +77 -77
- package/src/monaco-language-service/builtins.js +5 -0
- package/src/monaco-language-service/diagnostics.js +25 -3
- package/src/monaco-language-service/dts.js +550 -550
- package/src/output/classes.pyj +108 -8
- package/src/output/codegen.pyj +16 -2
- package/src/output/comments.pyj +45 -45
- package/src/output/exceptions.pyj +201 -105
- package/src/output/functions.pyj +9 -0
- package/src/output/jsx.pyj +164 -0
- package/src/output/literals.pyj +28 -2
- package/src/output/modules.pyj +1 -1
- package/src/output/operators.pyj +8 -2
- package/src/output/statements.pyj +2 -2
- package/src/output/stream.pyj +1 -0
- package/src/output/treeshake.pyj +182 -182
- package/src/output/utils.pyj +72 -72
- package/src/parse.pyj +417 -113
- package/src/string_interpolation.pyj +72 -72
- package/src/tokenizer.pyj +29 -0
- package/src/unicode_aliases.pyj +576 -576
- package/src/utils.pyj +192 -192
- package/test/_import_one.pyj +37 -37
- package/test/_import_two/__init__.pyj +11 -11
- package/test/_import_two/level2/deep.pyj +4 -4
- package/test/_import_two/other.pyj +6 -6
- package/test/_import_two/sub.pyj +13 -13
- package/test/aes_vectors.pyj +421 -421
- package/test/annotations.pyj +80 -80
- package/test/decorators.pyj +77 -77
- package/test/docstrings.pyj +39 -39
- package/test/elementmaker_test.pyj +45 -45
- package/test/functions.pyj +151 -151
- package/test/generators.pyj +41 -41
- package/test/generic.pyj +370 -370
- package/test/imports.pyj +72 -72
- package/test/internationalization.pyj +73 -73
- package/test/lint.pyj +164 -164
- package/test/loops.pyj +85 -85
- package/test/numpy.pyj +734 -734
- package/test/omit_function_metadata.pyj +20 -20
- package/test/python_features.pyj +19 -6
- package/test/regexp.pyj +55 -55
- package/test/repl.pyj +121 -121
- package/test/scoped_flags.pyj +76 -76
- package/test/unit/index.js +2177 -64
- package/test/unit/language-service-dts.js +543 -543
- package/test/unit/language-service-hover.js +455 -455
- package/test/unit/language-service.js +590 -4
- package/test/unit/web-repl.js +303 -0
- package/tools/cli.js +547 -547
- package/tools/compile.js +219 -219
- package/tools/completer.js +131 -131
- package/tools/embedded_compiler.js +251 -251
- package/tools/gettext.js +185 -185
- package/tools/ini.js +65 -65
- package/tools/msgfmt.js +187 -187
- package/tools/repl.js +223 -223
- package/tools/test.js +118 -118
- package/tools/utils.js +128 -128
- package/tools/web_repl.js +95 -95
- package/try +41 -41
- package/web-repl/env.js +196 -74
- package/web-repl/index.html +163 -163
- package/web-repl/main.js +252 -254
- package/web-repl/prism.css +139 -139
- package/web-repl/prism.js +113 -113
- package/web-repl/rapydscript.js +224 -102
- package/web-repl/sha1.js +25 -25
- package/hack_demo.pyj +0 -112
package/README.md
CHANGED
|
@@ -41,6 +41,7 @@ backwards compatible) features. For more on the forking, [see the bottom of this
|
|
|
41
41
|
- [Extended Subscript Syntax](#extended-subscript-syntax)
|
|
42
42
|
- [Variable Type Annotations](#variable-type-annotations)
|
|
43
43
|
- [Regular Expressions](#regular-expressions)
|
|
44
|
+
- [JSX Support](#jsx-support)
|
|
44
45
|
- [Creating DOM trees easily](#creating-dom-trees-easily)
|
|
45
46
|
- [Classes](#classes)
|
|
46
47
|
- [External Classes](#external-classes)
|
|
@@ -805,9 +806,9 @@ No special flag is required. The `+` operator compiles to a lightweight helper
|
|
|
805
806
|
|
|
806
807
|
Sets in RapydScript are identical to those in python. You can create them using
|
|
807
808
|
set literals or comprehensions and all set operations are supported. You can
|
|
808
|
-
store any object in a set
|
|
809
|
-
|
|
810
|
-
|
|
809
|
+
store any object in a set. For primitive types (strings, numbers) the value is
|
|
810
|
+
used for equality; for class instances, object identity (``is``) is used by
|
|
811
|
+
default unless the class defines a ``__hash__`` method.
|
|
811
812
|
|
|
812
813
|
Note that sets are not a subclass of the ES 6 JavaScript Set object, however,
|
|
813
814
|
they do use this object as a backend, when available. You can create a set from
|
|
@@ -835,8 +836,8 @@ a in s # True
|
|
|
835
836
|
[1, 2] in s # False
|
|
836
837
|
```
|
|
837
838
|
|
|
838
|
-
This is because
|
|
839
|
-
|
|
839
|
+
This is because list identity (not value) determines set membership for mutable
|
|
840
|
+
objects. Define ``__hash__`` on your own classes to control set/dict membership.
|
|
840
841
|
|
|
841
842
|
### Dicts
|
|
842
843
|
|
|
@@ -885,6 +886,63 @@ a = {1:1, 2:2}
|
|
|
885
886
|
isinstance(a, dict) == False # a is a normal JavaScript object
|
|
886
887
|
```
|
|
887
888
|
|
|
889
|
+
### List spread literals
|
|
890
|
+
|
|
891
|
+
RapydScript supports Python's `*expr` spread syntax inside list literals.
|
|
892
|
+
One or more `*expr` items can appear anywhere, interleaved with ordinary
|
|
893
|
+
elements:
|
|
894
|
+
|
|
895
|
+
```py
|
|
896
|
+
a = [1, 2, 3]
|
|
897
|
+
b = [4, 5]
|
|
898
|
+
|
|
899
|
+
# Spread at the end
|
|
900
|
+
result = [0, *a] # [0, 1, 2, 3]
|
|
901
|
+
|
|
902
|
+
# Spread in the middle
|
|
903
|
+
result = [0, *a, *b, 6] # [0, 1, 2, 3, 4, 5, 6]
|
|
904
|
+
|
|
905
|
+
# Copy a list
|
|
906
|
+
copy = [*a] # [1, 2, 3]
|
|
907
|
+
|
|
908
|
+
# Unpack a string
|
|
909
|
+
chars = [*'hello'] # ['h', 'e', 'l', 'l', 'o']
|
|
910
|
+
```
|
|
911
|
+
|
|
912
|
+
Spread works on any iterable (lists, strings, generators, `range()`).
|
|
913
|
+
The result is always a new Python list. Translates to JavaScript's
|
|
914
|
+
`[...expr]` spread syntax.
|
|
915
|
+
|
|
916
|
+
### Set spread literals
|
|
917
|
+
|
|
918
|
+
The same `*expr` syntax works inside set literals `{...}`:
|
|
919
|
+
|
|
920
|
+
```py
|
|
921
|
+
a = [1, 2, 3]
|
|
922
|
+
b = [3, 4, 5]
|
|
923
|
+
|
|
924
|
+
s = {*a, *b} # set([1, 2, 3, 4, 5]) — duplicates removed
|
|
925
|
+
s2 = {*a, 10} # set([1, 2, 3, 10])
|
|
926
|
+
```
|
|
927
|
+
|
|
928
|
+
Translates to `ρσ_set([...a, ...b])`.
|
|
929
|
+
|
|
930
|
+
### `**expr` in function calls
|
|
931
|
+
|
|
932
|
+
`**expr` in a function call now accepts any expression, not just a plain
|
|
933
|
+
variable name:
|
|
934
|
+
|
|
935
|
+
```py
|
|
936
|
+
def f(x=0, y=0):
|
|
937
|
+
return x + y
|
|
938
|
+
|
|
939
|
+
opts = {'x': 10, 'y': 20}
|
|
940
|
+
f(**opts) # 30 (variable — always worked)
|
|
941
|
+
f(**{'x': 1, 'y': 2}) # 3 (dict literal)
|
|
942
|
+
f(**cfg.defaults) # uses attribute access result
|
|
943
|
+
f(**get_opts()) # uses function call result
|
|
944
|
+
```
|
|
945
|
+
|
|
888
946
|
### Dict merge literals
|
|
889
947
|
|
|
890
948
|
RapydScript supports Python's `{**d1, **d2}` dict merge (spread) syntax.
|
|
@@ -1173,7 +1231,8 @@ semantics:
|
|
|
1173
1231
|
| other `float` | derived from the bit pattern |
|
|
1174
1232
|
| `str` | djb2 algorithm — stable within a process |
|
|
1175
1233
|
| object with `__hash__` | dispatches to `__hash__()` |
|
|
1176
|
-
| class instance | stable identity hash (assigned on first call) |
|
|
1234
|
+
| class instance (no `__hash__`) | stable identity hash (assigned on first call) |
|
|
1235
|
+
| class with `__eq__` but no `__hash__` | `TypeError` (unhashable — Python semantics) |
|
|
1177
1236
|
| `list` | `TypeError: unhashable type: 'list'` |
|
|
1178
1237
|
| `set` | `TypeError: unhashable type: 'set'` |
|
|
1179
1238
|
| `dict` | `TypeError: unhashable type: 'dict'` |
|
|
@@ -1193,8 +1252,67 @@ class Point:
|
|
|
1193
1252
|
return self.x * 31 + self.y
|
|
1194
1253
|
|
|
1195
1254
|
hash(Point(1, 2)) # 33
|
|
1255
|
+
|
|
1256
|
+
# Python semantics: __eq__ without __hash__ → unhashable
|
|
1257
|
+
class Bar:
|
|
1258
|
+
def __eq__(self, other):
|
|
1259
|
+
return True
|
|
1260
|
+
hash(Bar()) # TypeError: unhashable type: 'Bar'
|
|
1196
1261
|
```
|
|
1197
1262
|
|
|
1263
|
+
### Attribute-Access Dunders
|
|
1264
|
+
|
|
1265
|
+
RapydScript supports the four Python attribute-interception hooks:
|
|
1266
|
+
`__getattr__`, `__setattr__`, `__delattr__`, and `__getattribute__`.
|
|
1267
|
+
When a class defines any of them, instances are automatically wrapped in a
|
|
1268
|
+
JavaScript `Proxy` that routes attribute access through the hooks — including
|
|
1269
|
+
accesses that occur inside `__init__`.
|
|
1270
|
+
|
|
1271
|
+
| Hook | When called |
|
|
1272
|
+
|---|---|
|
|
1273
|
+
| `__getattr__(self, name)` | Fallback — only called when normal lookup finds nothing |
|
|
1274
|
+
| `__setattr__(self, name, value)` | Every attribute assignment (including `self.x = …` in `__init__`) |
|
|
1275
|
+
| `__delattr__(self, name)` | Every `del obj.attr` |
|
|
1276
|
+
| `__getattribute__(self, name)` | Every attribute read (overrides normal lookup) |
|
|
1277
|
+
|
|
1278
|
+
To bypass the hooks from within the hook itself (avoiding infinite recursion),
|
|
1279
|
+
use the `object.*` bypass functions:
|
|
1280
|
+
|
|
1281
|
+
| Python idiom | Compiled form | Effect |
|
|
1282
|
+
|---|---|---|
|
|
1283
|
+
| `object.__setattr__(self, name, val)` | `ρσ_object_setattr(self, name, val)` | Set attribute directly, bypassing `__setattr__` |
|
|
1284
|
+
| `object.__getattribute__(self, name)` | `ρσ_object_getattr(self, name)` | Read attribute directly, bypassing `__getattribute__` |
|
|
1285
|
+
| `object.__delattr__(self, name)` | `ρσ_object_delattr(self, name)` | Delete attribute directly, bypassing `__delattr__` |
|
|
1286
|
+
|
|
1287
|
+
Subclasses automatically inherit proxy wrapping from their parent class — if
|
|
1288
|
+
`Base` defines `__getattr__`, all `Child(Base)` instances are also Proxy-wrapped.
|
|
1289
|
+
|
|
1290
|
+
```py
|
|
1291
|
+
class Validated:
|
|
1292
|
+
"""Reject negative values at assignment time."""
|
|
1293
|
+
def __setattr__(self, name, value):
|
|
1294
|
+
if jstype(value) is 'number' and value < 0:
|
|
1295
|
+
raise ValueError(name + ' must be non-negative')
|
|
1296
|
+
object.__setattr__(self, name, value)
|
|
1297
|
+
|
|
1298
|
+
v = Validated()
|
|
1299
|
+
v.x = 5 # ok
|
|
1300
|
+
v.x = -1 # ValueError: x must be non-negative
|
|
1301
|
+
|
|
1302
|
+
class AttrProxy:
|
|
1303
|
+
"""Log every attribute read."""
|
|
1304
|
+
def __init__(self):
|
|
1305
|
+
object.__setattr__(self, '_log', [])
|
|
1306
|
+
|
|
1307
|
+
def __getattribute__(self, name):
|
|
1308
|
+
self._log.append(name) # self._log goes through __getattribute__ too!
|
|
1309
|
+
return object.__getattribute__(self, name)
|
|
1310
|
+
```
|
|
1311
|
+
|
|
1312
|
+
> **Proxy support required** — The hooks rely on `Proxy`, which is available
|
|
1313
|
+
> in all modern browsers and Node.js ≥ 6. In environments that lack `Proxy`
|
|
1314
|
+
> the class still works, but the hooks are silently bypassed.
|
|
1315
|
+
|
|
1198
1316
|
Loops
|
|
1199
1317
|
-----
|
|
1200
1318
|
RapydScript's loops work like Python, not JavaScript. You can't, for example
|
|
@@ -1405,6 +1523,16 @@ Case-folding for locale-insensitive lowercase comparison:
|
|
|
1405
1523
|
str.casefold('ÄÖÜ') == str.casefold('äöü') # True (maps to lowercase)
|
|
1406
1524
|
```
|
|
1407
1525
|
|
|
1526
|
+
Tab expansion:
|
|
1527
|
+
|
|
1528
|
+
```py
|
|
1529
|
+
str.expandtabs('a\tb', 4) # 'a b' — expand to next 4-space tab stop
|
|
1530
|
+
str.expandtabs('\t\t', 8) # ' ' — two full tab stops
|
|
1531
|
+
str.expandtabs('ab\tc', 4) # 'ab c' — only 2 spaces needed to reach next stop
|
|
1532
|
+
```
|
|
1533
|
+
|
|
1534
|
+
The optional `tabsize` argument defaults to `8`, matching Python's default. A `tabsize` of `0` removes all tab characters. Newline (`\n`) and carriage-return (`\r`) characters reset the column counter, so each line is expanded independently.
|
|
1535
|
+
|
|
1408
1536
|
However, if you want to make the python string methods available on string
|
|
1409
1537
|
objects, there is a convenience method in the standard library to do so. Use
|
|
1410
1538
|
the following code:
|
|
@@ -1612,6 +1740,7 @@ can annotate a variable with a type hint, with or without an initial value:
|
|
|
1612
1740
|
x: int = 42
|
|
1613
1741
|
name: str = "Alice"
|
|
1614
1742
|
items: list = [1, 2, 3]
|
|
1743
|
+
coords: tuple = (10, 20)
|
|
1615
1744
|
|
|
1616
1745
|
# Annotation only: declares the type without assigning a value
|
|
1617
1746
|
count: int
|
|
@@ -1684,6 +1813,353 @@ re.match(///
|
|
|
1684
1813
|
///, 'ab')
|
|
1685
1814
|
```
|
|
1686
1815
|
|
|
1816
|
+
JSX Support
|
|
1817
|
+
-----------
|
|
1818
|
+
|
|
1819
|
+
RapydScript supports JSX syntax for building React UI components. JSX elements compile directly to `React.createElement()` calls, so the output is plain JavaScript — no Babel or JSX transform step is needed.
|
|
1820
|
+
|
|
1821
|
+
Enable JSX support with:
|
|
1822
|
+
|
|
1823
|
+
```py
|
|
1824
|
+
from __python__ import jsx
|
|
1825
|
+
```
|
|
1826
|
+
|
|
1827
|
+
### Requirements
|
|
1828
|
+
|
|
1829
|
+
`React` must be in scope at runtime. How you provide it depends on your environment:
|
|
1830
|
+
|
|
1831
|
+
- **Bundler (Vite, webpack, etc.):** `import React from 'react'` at the top of your file (or configure your bundler's global React shim).
|
|
1832
|
+
- **CDN / browser script tag:** load React before your compiled script.
|
|
1833
|
+
- **Bitburner:** React is already available as a global — no import needed.
|
|
1834
|
+
- **RapydScript web REPL:** a minimal React stub is injected automatically so `React.createElement` calls succeed.
|
|
1835
|
+
|
|
1836
|
+
### Output format
|
|
1837
|
+
|
|
1838
|
+
RapydScript compiles JSX to `React.createElement()` calls. For example:
|
|
1839
|
+
|
|
1840
|
+
```py
|
|
1841
|
+
from __python__ import jsx
|
|
1842
|
+
|
|
1843
|
+
def Greeting(props):
|
|
1844
|
+
return <h1>Hello, {props.name}!</h1>
|
|
1845
|
+
```
|
|
1846
|
+
|
|
1847
|
+
Compiles to:
|
|
1848
|
+
|
|
1849
|
+
```js
|
|
1850
|
+
function Greeting(props) {
|
|
1851
|
+
return React.createElement("h1", null, "Hello, ", props.name);
|
|
1852
|
+
}
|
|
1853
|
+
```
|
|
1854
|
+
|
|
1855
|
+
Lowercase tags (`div`, `span`, `h1`, …) become string arguments. Capitalised names and dot-notation (`MyComponent`, `Router.Route`) are passed as references — not strings.
|
|
1856
|
+
|
|
1857
|
+
### Attributes
|
|
1858
|
+
|
|
1859
|
+
String, expression, boolean, and hyphenated attribute names all work:
|
|
1860
|
+
|
|
1861
|
+
```py
|
|
1862
|
+
from __python__ import jsx
|
|
1863
|
+
|
|
1864
|
+
def Form(props):
|
|
1865
|
+
return (
|
|
1866
|
+
<form>
|
|
1867
|
+
<input
|
|
1868
|
+
type="text"
|
|
1869
|
+
aria-label="Name"
|
|
1870
|
+
disabled={props.readonly}
|
|
1871
|
+
onChange={props.onChange}
|
|
1872
|
+
required
|
|
1873
|
+
/>
|
|
1874
|
+
</form>
|
|
1875
|
+
)
|
|
1876
|
+
```
|
|
1877
|
+
|
|
1878
|
+
Hyphenated names (e.g. `aria-label`, `data-id`) are automatically quoted as object keys: `{"aria-label": "Name"}`. Boolean attributes with no value compile to `true`.
|
|
1879
|
+
|
|
1880
|
+
### Nested elements and expressions
|
|
1881
|
+
|
|
1882
|
+
```py
|
|
1883
|
+
from __python__ import jsx
|
|
1884
|
+
|
|
1885
|
+
def UserList(users):
|
|
1886
|
+
return (
|
|
1887
|
+
<ul className="user-list">
|
|
1888
|
+
{[<li key={u.id}>{u.name}</li> for u in users]}
|
|
1889
|
+
</ul>
|
|
1890
|
+
)
|
|
1891
|
+
```
|
|
1892
|
+
|
|
1893
|
+
### Fragments
|
|
1894
|
+
|
|
1895
|
+
Use `<>...</>` to return multiple elements without a wrapper node. Fragments compile to `React.createElement(React.Fragment, null, ...)`:
|
|
1896
|
+
|
|
1897
|
+
```py
|
|
1898
|
+
from __python__ import jsx
|
|
1899
|
+
|
|
1900
|
+
def TwoItems():
|
|
1901
|
+
return (
|
|
1902
|
+
<>
|
|
1903
|
+
<span>First</span>
|
|
1904
|
+
<span>Second</span>
|
|
1905
|
+
</>
|
|
1906
|
+
)
|
|
1907
|
+
```
|
|
1908
|
+
|
|
1909
|
+
### Self-closing elements
|
|
1910
|
+
|
|
1911
|
+
```py
|
|
1912
|
+
from __python__ import jsx
|
|
1913
|
+
|
|
1914
|
+
def Avatar(props):
|
|
1915
|
+
return <img src={props.url} alt={props.name} />
|
|
1916
|
+
```
|
|
1917
|
+
|
|
1918
|
+
### Spread attributes
|
|
1919
|
+
|
|
1920
|
+
```py
|
|
1921
|
+
from __python__ import jsx
|
|
1922
|
+
|
|
1923
|
+
def Button(props):
|
|
1924
|
+
return <button {...props}>Click me</button>
|
|
1925
|
+
```
|
|
1926
|
+
|
|
1927
|
+
Compiles to `React.createElement("button", {...props}, "Click me")`.
|
|
1928
|
+
|
|
1929
|
+
### Component tags
|
|
1930
|
+
|
|
1931
|
+
Capitalised names and dot-notation are treated as component references (not quoted strings):
|
|
1932
|
+
|
|
1933
|
+
```py
|
|
1934
|
+
from __python__ import jsx
|
|
1935
|
+
|
|
1936
|
+
def App():
|
|
1937
|
+
return (
|
|
1938
|
+
<Router.Provider>
|
|
1939
|
+
<MyComponent name="hello" />
|
|
1940
|
+
</Router.Provider>
|
|
1941
|
+
)
|
|
1942
|
+
```
|
|
1943
|
+
|
|
1944
|
+
Compiles to:
|
|
1945
|
+
|
|
1946
|
+
```js
|
|
1947
|
+
React.createElement(Router.Provider, null,
|
|
1948
|
+
React.createElement(MyComponent, {name: "hello"})
|
|
1949
|
+
)
|
|
1950
|
+
```
|
|
1951
|
+
|
|
1952
|
+
### Compiling JSX files
|
|
1953
|
+
|
|
1954
|
+
Since the output is plain JavaScript, compile to a `.js` file as normal:
|
|
1955
|
+
|
|
1956
|
+
```sh
|
|
1957
|
+
rapydscript mycomponent.pyj --output mycomponent.js
|
|
1958
|
+
```
|
|
1959
|
+
|
|
1960
|
+
React Standard Library
|
|
1961
|
+
-----------------------
|
|
1962
|
+
|
|
1963
|
+
RapydScript ships a `react` standard library module that re-exports every standard React hook and utility under their familiar Python-friendly names. Import the pieces you need and the compiler will resolve each name to the corresponding `React.*` property at compile time.
|
|
1964
|
+
|
|
1965
|
+
### Importing hooks
|
|
1966
|
+
|
|
1967
|
+
```py
|
|
1968
|
+
from __python__ import jsx
|
|
1969
|
+
from react import useState, useEffect, useCallback, useMemo, useRef
|
|
1970
|
+
|
|
1971
|
+
def Counter():
|
|
1972
|
+
count, setCount = useState(0)
|
|
1973
|
+
|
|
1974
|
+
def increment():
|
|
1975
|
+
setCount(count + 1)
|
|
1976
|
+
|
|
1977
|
+
return <button onClick={increment}>{count}</button>
|
|
1978
|
+
```
|
|
1979
|
+
|
|
1980
|
+
Compiles to:
|
|
1981
|
+
|
|
1982
|
+
```js
|
|
1983
|
+
var useState = React.useState;
|
|
1984
|
+
// ...
|
|
1985
|
+
function Counter() {
|
|
1986
|
+
var [count, setCount] = React.useState(0);
|
|
1987
|
+
function increment() {
|
|
1988
|
+
setCount(count + 1);
|
|
1989
|
+
}
|
|
1990
|
+
return React.createElement("button", {onClick: increment}, count);
|
|
1991
|
+
}
|
|
1992
|
+
```
|
|
1993
|
+
|
|
1994
|
+
Tuple unpacking works naturally because `React.useState` returns a two-element array — `count, setCount = useState(0)` compiles to the ES6 destructuring `var [count, setCount] = React.useState(0)`.
|
|
1995
|
+
|
|
1996
|
+
### Available exports
|
|
1997
|
+
|
|
1998
|
+
**Hooks (React 16.8+)**
|
|
1999
|
+
|
|
2000
|
+
| Import name | React API |
|
|
2001
|
+
|---|---|
|
|
2002
|
+
| `useState` | `React.useState` |
|
|
2003
|
+
| `useEffect` | `React.useEffect` |
|
|
2004
|
+
| `useContext` | `React.useContext` |
|
|
2005
|
+
| `useReducer` | `React.useReducer` |
|
|
2006
|
+
| `useCallback` | `React.useCallback` |
|
|
2007
|
+
| `useMemo` | `React.useMemo` |
|
|
2008
|
+
| `useRef` | `React.useRef` |
|
|
2009
|
+
| `useImperativeHandle` | `React.useImperativeHandle` |
|
|
2010
|
+
| `useLayoutEffect` | `React.useLayoutEffect` |
|
|
2011
|
+
| `useDebugValue` | `React.useDebugValue` |
|
|
2012
|
+
|
|
2013
|
+
**Hooks (React 18+)**
|
|
2014
|
+
|
|
2015
|
+
| Import name | React API |
|
|
2016
|
+
|---|---|
|
|
2017
|
+
| `useId` | `React.useId` |
|
|
2018
|
+
| `useTransition` | `React.useTransition` |
|
|
2019
|
+
| `useDeferredValue` | `React.useDeferredValue` |
|
|
2020
|
+
| `useSyncExternalStore` | `React.useSyncExternalStore` |
|
|
2021
|
+
| `useInsertionEffect` | `React.useInsertionEffect` |
|
|
2022
|
+
|
|
2023
|
+
**Core classes and elements**
|
|
2024
|
+
|
|
2025
|
+
| Import name | React API |
|
|
2026
|
+
|---|---|
|
|
2027
|
+
| `Component` | `React.Component` |
|
|
2028
|
+
| `PureComponent` | `React.PureComponent` |
|
|
2029
|
+
| `Fragment` | `React.Fragment` |
|
|
2030
|
+
| `StrictMode` | `React.StrictMode` |
|
|
2031
|
+
| `Suspense` | `React.Suspense` |
|
|
2032
|
+
| `Profiler` | `React.Profiler` |
|
|
2033
|
+
|
|
2034
|
+
**Utilities**
|
|
2035
|
+
|
|
2036
|
+
| Import name | React API |
|
|
2037
|
+
|---|---|
|
|
2038
|
+
| `createElement` | `React.createElement` |
|
|
2039
|
+
| `cloneElement` | `React.cloneElement` |
|
|
2040
|
+
| `createContext` | `React.createContext` |
|
|
2041
|
+
| `createRef` | `React.createRef` |
|
|
2042
|
+
| `forwardRef` | `React.forwardRef` |
|
|
2043
|
+
| `isValidElement` | `React.isValidElement` |
|
|
2044
|
+
| `memo` | `React.memo` |
|
|
2045
|
+
| `lazy` | `React.lazy` |
|
|
2046
|
+
|
|
2047
|
+
### Common patterns
|
|
2048
|
+
|
|
2049
|
+
**useEffect with cleanup**
|
|
2050
|
+
|
|
2051
|
+
```py
|
|
2052
|
+
from react import useState, useEffect
|
|
2053
|
+
|
|
2054
|
+
def Timer():
|
|
2055
|
+
count, setCount = useState(0)
|
|
2056
|
+
def setup():
|
|
2057
|
+
interval = setInterval(def(): setCount(count + 1);, 1000)
|
|
2058
|
+
def cleanup():
|
|
2059
|
+
clearInterval(interval)
|
|
2060
|
+
return cleanup
|
|
2061
|
+
useEffect(setup, [count])
|
|
2062
|
+
return count
|
|
2063
|
+
```
|
|
2064
|
+
|
|
2065
|
+
**useReducer**
|
|
2066
|
+
|
|
2067
|
+
```py
|
|
2068
|
+
from react import useReducer
|
|
2069
|
+
|
|
2070
|
+
def reducer(state, action):
|
|
2071
|
+
if action.type == 'increment':
|
|
2072
|
+
return state + 1
|
|
2073
|
+
if action.type == 'decrement':
|
|
2074
|
+
return state - 1
|
|
2075
|
+
return state
|
|
2076
|
+
|
|
2077
|
+
def Counter():
|
|
2078
|
+
state, dispatch = useReducer(reducer, 0)
|
|
2079
|
+
def inc():
|
|
2080
|
+
dispatch({'type': 'increment'})
|
|
2081
|
+
return state
|
|
2082
|
+
```
|
|
2083
|
+
|
|
2084
|
+
**useContext**
|
|
2085
|
+
|
|
2086
|
+
```py
|
|
2087
|
+
from react import createContext, useContext
|
|
2088
|
+
|
|
2089
|
+
ThemeContext = createContext('light')
|
|
2090
|
+
|
|
2091
|
+
def ThemedButton():
|
|
2092
|
+
theme = useContext(ThemeContext)
|
|
2093
|
+
return theme
|
|
2094
|
+
```
|
|
2095
|
+
|
|
2096
|
+
**useRef**
|
|
2097
|
+
|
|
2098
|
+
```py
|
|
2099
|
+
from __python__ import jsx
|
|
2100
|
+
from react import useRef
|
|
2101
|
+
|
|
2102
|
+
def FocusInput():
|
|
2103
|
+
inputRef = useRef(None)
|
|
2104
|
+
def handleClick():
|
|
2105
|
+
inputRef.current.focus()
|
|
2106
|
+
return <input ref={inputRef} />
|
|
2107
|
+
```
|
|
2108
|
+
|
|
2109
|
+
**memo**
|
|
2110
|
+
|
|
2111
|
+
```py
|
|
2112
|
+
from __python__ import jsx
|
|
2113
|
+
from react import memo
|
|
2114
|
+
|
|
2115
|
+
def Row(props):
|
|
2116
|
+
return <li>{props.label}</li>
|
|
2117
|
+
|
|
2118
|
+
MemoRow = memo(Row)
|
|
2119
|
+
```
|
|
2120
|
+
|
|
2121
|
+
**forwardRef**
|
|
2122
|
+
|
|
2123
|
+
```py
|
|
2124
|
+
from __python__ import jsx
|
|
2125
|
+
from react import forwardRef
|
|
2126
|
+
|
|
2127
|
+
def FancyInput(props, ref):
|
|
2128
|
+
return <input ref={ref} placeholder={props.placeholder} />
|
|
2129
|
+
|
|
2130
|
+
FancyInputWithRef = forwardRef(FancyInput)
|
|
2131
|
+
```
|
|
2132
|
+
|
|
2133
|
+
**Class component**
|
|
2134
|
+
|
|
2135
|
+
You can extend `React.Component` directly without importing it, or import `Component` from the `react` module:
|
|
2136
|
+
|
|
2137
|
+
```py
|
|
2138
|
+
from __python__ import jsx
|
|
2139
|
+
from react import Component
|
|
2140
|
+
|
|
2141
|
+
class Greeter(Component):
|
|
2142
|
+
def render(self):
|
|
2143
|
+
return <h1>Hello, {self.props.name}!</h1>
|
|
2144
|
+
```
|
|
2145
|
+
|
|
2146
|
+
**useTransition (React 18)**
|
|
2147
|
+
|
|
2148
|
+
```py
|
|
2149
|
+
from react import useState, useTransition
|
|
2150
|
+
|
|
2151
|
+
def SearchInput():
|
|
2152
|
+
isPending, startTransition = useTransition()
|
|
2153
|
+
query, setQuery = useState('')
|
|
2154
|
+
def handleChange(e):
|
|
2155
|
+
startTransition(def(): setQuery(e.target.value);)
|
|
2156
|
+
return isPending
|
|
2157
|
+
```
|
|
2158
|
+
|
|
2159
|
+
### Requirements
|
|
2160
|
+
|
|
2161
|
+
The `react` module does not bundle React itself — it provides compile-time name bindings only. `React` must be available as a global variable at runtime, exactly as described in the [JSX Requirements](#requirements) section above.
|
|
2162
|
+
|
|
1687
2163
|
Creating DOM trees easily
|
|
1688
2164
|
---------------------------------
|
|
1689
2165
|
|
|
@@ -1914,6 +2390,117 @@ print(Counter.get_count()) # 2
|
|
|
1914
2390
|
|
|
1915
2391
|
The `@classmethod` decorator compiles to a method placed directly on the class (not its prototype), with `cls` mapped to `this`. A prototype delegation shim is also generated so instance calls work correctly.
|
|
1916
2392
|
|
|
2393
|
+
### `__new__` Constructor Hook
|
|
2394
|
+
|
|
2395
|
+
RapydScript supports Python's `__new__` method, which runs *before* `__init__` and controls instance creation. Use it to implement patterns like singletons or alternative constructors:
|
|
2396
|
+
|
|
2397
|
+
```py
|
|
2398
|
+
class Singleton:
|
|
2399
|
+
_instance = None
|
|
2400
|
+
def __new__(cls):
|
|
2401
|
+
if cls._instance is None:
|
|
2402
|
+
cls._instance = super().__new__(cls)
|
|
2403
|
+
return cls._instance
|
|
2404
|
+
def __init__(self):
|
|
2405
|
+
pass
|
|
2406
|
+
|
|
2407
|
+
a = Singleton()
|
|
2408
|
+
b = Singleton()
|
|
2409
|
+
assert a is b # same instance
|
|
2410
|
+
```
|
|
2411
|
+
|
|
2412
|
+
`super().__new__(cls)` creates a bare instance of `cls` (equivalent to `Object.create(cls.prototype)` in JavaScript). If `__new__` returns an instance of the class, `__init__` is called on it automatically. If it returns something else, `__init__` is skipped.
|
|
2413
|
+
|
|
2414
|
+
Class variables accessed via `cls` inside `__new__` are correctly rewritten to `cls.prototype.varname`, matching Python's semantics.
|
|
2415
|
+
|
|
2416
|
+
### `__class_getitem__`
|
|
2417
|
+
|
|
2418
|
+
RapydScript supports Python's `__class_getitem__` hook, which enables subscript syntax on a class itself (`MyClass[item]`). Define `__class_getitem__(cls, item)` in a class body to intercept `ClassName[x]`:
|
|
2419
|
+
|
|
2420
|
+
```py
|
|
2421
|
+
class Box:
|
|
2422
|
+
def __class_getitem__(cls, item):
|
|
2423
|
+
return cls.__name__ + '[' + str(item) + ']'
|
|
2424
|
+
|
|
2425
|
+
print(Box[int]) # Box[<class 'int'>]
|
|
2426
|
+
print(Box['str']) # Box[str]
|
|
2427
|
+
```
|
|
2428
|
+
|
|
2429
|
+
`__class_getitem__` is an implicit `@classmethod`: the compiler strips `cls` from the JS parameter list and maps it to `this`, so calling `Box[item]` compiles to `Box.__class_getitem__(item)` with `this = Box`.
|
|
2430
|
+
|
|
2431
|
+
Subclasses inherit `__class_getitem__` from their parent and receive the subclass as `cls`:
|
|
2432
|
+
|
|
2433
|
+
```py
|
|
2434
|
+
class Base:
|
|
2435
|
+
def __class_getitem__(cls, item):
|
|
2436
|
+
return cls.__name__ + '<' + str(item) + '>'
|
|
2437
|
+
|
|
2438
|
+
class Child(Base):
|
|
2439
|
+
pass
|
|
2440
|
+
|
|
2441
|
+
print(Base[42]) # Base<42>
|
|
2442
|
+
print(Child[42]) # Child<42>
|
|
2443
|
+
```
|
|
2444
|
+
|
|
2445
|
+
Class variables declared in the class body are accessible via `cls.varname` inside `__class_getitem__`, just as with `@classmethod`.
|
|
2446
|
+
|
|
2447
|
+
### `__init_subclass__`
|
|
2448
|
+
|
|
2449
|
+
`__init_subclass__` is a hook that is called automatically on a base class whenever a subclass is created. It is an implicit `@classmethod`: the compiler strips `cls` from the JS signature and maps it to `this`, so `cls` receives the newly-created subclass.
|
|
2450
|
+
|
|
2451
|
+
```py
|
|
2452
|
+
class PluginBase:
|
|
2453
|
+
_plugins = []
|
|
2454
|
+
|
|
2455
|
+
def __init_subclass__(cls, **kwargs):
|
|
2456
|
+
PluginBase._plugins.append(cls)
|
|
2457
|
+
|
|
2458
|
+
class AudioPlugin(PluginBase):
|
|
2459
|
+
pass
|
|
2460
|
+
|
|
2461
|
+
class VideoPlugin(PluginBase):
|
|
2462
|
+
pass
|
|
2463
|
+
|
|
2464
|
+
print(len(PluginBase._plugins)) # 2
|
|
2465
|
+
print(PluginBase._plugins[0].__name__) # AudioPlugin
|
|
2466
|
+
```
|
|
2467
|
+
|
|
2468
|
+
Keyword arguments written in the class header are forwarded to `__init_subclass__`:
|
|
2469
|
+
|
|
2470
|
+
```py
|
|
2471
|
+
class Base:
|
|
2472
|
+
def __init_subclass__(cls, required=False, **kwargs):
|
|
2473
|
+
cls._required = required
|
|
2474
|
+
|
|
2475
|
+
class Strict(Base, required=True):
|
|
2476
|
+
pass
|
|
2477
|
+
|
|
2478
|
+
class Loose(Base):
|
|
2479
|
+
pass
|
|
2480
|
+
|
|
2481
|
+
print(Strict._required) # True
|
|
2482
|
+
print(Loose._required) # False
|
|
2483
|
+
```
|
|
2484
|
+
|
|
2485
|
+
Use `super().__init_subclass__(**kwargs)` to propagate the hook up the hierarchy:
|
|
2486
|
+
|
|
2487
|
+
```py
|
|
2488
|
+
class GrandParent:
|
|
2489
|
+
def __init_subclass__(cls, **kwargs):
|
|
2490
|
+
cls._from_grandparent = True
|
|
2491
|
+
|
|
2492
|
+
class Parent(GrandParent):
|
|
2493
|
+
def __init_subclass__(cls, **kwargs):
|
|
2494
|
+
super().__init_subclass__(**kwargs) # propagates to GrandParent
|
|
2495
|
+
|
|
2496
|
+
class Child(Parent):
|
|
2497
|
+
pass
|
|
2498
|
+
|
|
2499
|
+
print(Child._from_grandparent) # True
|
|
2500
|
+
```
|
|
2501
|
+
|
|
2502
|
+
The hook is called after the subclass is fully set up (including `__name__`, `__qualname__`, and `__module__`), so `cls.__name__` is always the correct subclass name inside the hook.
|
|
2503
|
+
|
|
1917
2504
|
### Nested Classes
|
|
1918
2505
|
|
|
1919
2506
|
A class may be defined inside another class. The nested class becomes an attribute of the outer class (accessible as `Outer.Inner`) and is also reachable via instances (`self.Inner` inside methods). This mirrors Python semantics exactly.
|
|
@@ -2350,6 +2937,45 @@ except SomeInternalError:
|
|
|
2350
2937
|
|
|
2351
2938
|
Basically, `try/except/finally` in RapydScript works very similar to the way it does in Python 3.
|
|
2352
2939
|
|
|
2940
|
+
### Exception Groups (`except*`, Python 3.11+)
|
|
2941
|
+
|
|
2942
|
+
RapydScript supports exception groups via the `ExceptionGroup` class and `except*` syntax. An `ExceptionGroup` bundles multiple exceptions under a single message:
|
|
2943
|
+
|
|
2944
|
+
```py
|
|
2945
|
+
eg = ExceptionGroup("network errors", [
|
|
2946
|
+
TimeoutError("host A timed out"),
|
|
2947
|
+
TimeoutError("host B timed out"),
|
|
2948
|
+
ValueError("bad address"),
|
|
2949
|
+
])
|
|
2950
|
+
raise eg
|
|
2951
|
+
```
|
|
2952
|
+
|
|
2953
|
+
Use `except*` to handle exceptions by type — each handler receives a sub-group containing only the matching exceptions:
|
|
2954
|
+
|
|
2955
|
+
```py
|
|
2956
|
+
try:
|
|
2957
|
+
fetch_all()
|
|
2958
|
+
except* TimeoutError as group:
|
|
2959
|
+
for e in group.exceptions:
|
|
2960
|
+
print("timeout:", e)
|
|
2961
|
+
except* ValueError as group:
|
|
2962
|
+
print("bad input:", group.exceptions[0])
|
|
2963
|
+
```
|
|
2964
|
+
|
|
2965
|
+
- Each `except*` clause sees the exceptions not already matched by earlier clauses.
|
|
2966
|
+
- Any unmatched exceptions are automatically re-raised as a new `ExceptionGroup`.
|
|
2967
|
+
- A bare `except*:` (no type) catches all remaining exceptions.
|
|
2968
|
+
- You cannot mix `except` and `except*` in the same `try` block.
|
|
2969
|
+
- Plain (non-group) exceptions can also be caught with `except*`; the variable is bound to the exception itself rather than a sub-group.
|
|
2970
|
+
|
|
2971
|
+
`ExceptionGroup` also provides `subgroup(condition)` and `split(condition)` for programmatic filtering, where `condition` is either an exception class or a predicate function:
|
|
2972
|
+
|
|
2973
|
+
```py
|
|
2974
|
+
eg = ExceptionGroup("mixed", [ValueError("v"), TypeError("t")])
|
|
2975
|
+
ve_group = eg.subgroup(ValueError) # ExceptionGroup of just ValueErrors
|
|
2976
|
+
matched, rest = eg.split(ValueError) # (ve_group, te_group)
|
|
2977
|
+
```
|
|
2978
|
+
|
|
2353
2979
|
Scope Control
|
|
2354
2980
|
-------------
|
|
2355
2981
|
|
|
@@ -2417,6 +3043,7 @@ One of Python's main strengths is the number of libraries available to the devel
|
|
|
2417
3043
|
operator # a subset of Python's operator module
|
|
2418
3044
|
functools # reduce, partial, wraps, lru_cache, cache, total_ordering, cmp_to_key
|
|
2419
3045
|
collections # namedtuple, deque, Counter, OrderedDict, defaultdict
|
|
3046
|
+
copy # copy (shallow), deepcopy; honours __copy__ / __deepcopy__ hooks
|
|
2420
3047
|
itertools # count, cycle, repeat, accumulate, chain, compress, dropwhile, filterfalse,
|
|
2421
3048
|
# groupby, islice, pairwise, starmap, takewhile, zip_longest,
|
|
2422
3049
|
# product, permutations, combinations, combinations_with_replacement
|
|
@@ -2661,6 +3288,31 @@ below:
|
|
|
2661
3288
|
should use a scoped flag. See the section on dictionaries above for details.
|
|
2662
3289
|
|
|
2663
3290
|
|
|
3291
|
+
Python Flags
|
|
3292
|
+
------------
|
|
3293
|
+
|
|
3294
|
+
Python flags are scoped compiler directives that opt in to stricter Python
|
|
3295
|
+
semantics or language features. In source code they are written as:
|
|
3296
|
+
|
|
3297
|
+
```py
|
|
3298
|
+
from __python__ import flag_name
|
|
3299
|
+
```
|
|
3300
|
+
|
|
3301
|
+
At the top level they take effect for the rest of the file; inside a function
|
|
3302
|
+
or class body they apply only to that scope. Prefix a flag with `no_` to turn
|
|
3303
|
+
it off in a nested scope.
|
|
3304
|
+
|
|
3305
|
+
| Flag | Description |
|
|
3306
|
+
|---|---|
|
|
3307
|
+
| `dict_literals` | `{k: v}` literals create Python `dict` objects instead of plain JS objects. |
|
|
3308
|
+
| `overload_getitem` | `obj[key]` dispatches to `__getitem__` / `__setitem__` / `__delitem__` on objects that define them. |
|
|
3309
|
+
| `overload_operators` | Arithmetic and bitwise operators (`+`, `-`, `*`, `/`, `//`, `%`, `**`, `&`, `\|`, `^`, `<<`, `>>`) dispatch to dunder methods (`__add__`, `__sub__`, etc.) and their reflected variants. Unary `-`/`+`/`~` dispatch to `__neg__`/`__pos__`/`__invert__`. |
|
|
3310
|
+
| `truthiness` | Boolean tests and `bool()` dispatch to `__bool__` and treat empty containers as falsy, matching Python semantics. |
|
|
3311
|
+
| `bound_methods` | Method references (`obj.method`) are automatically bound to their object, so they can be passed as callbacks without losing `self`. |
|
|
3312
|
+
| `hash_literals` | `{k: v}` creates a Python `dict` (alias for `dict_literals`; kept for backward compatibility). |
|
|
3313
|
+
| `jsx` | Enable JSX syntax (`<Tag attr={expr}>children</Tag>`). Required for files that contain JSX elements. |
|
|
3314
|
+
|
|
3315
|
+
|
|
2664
3316
|
Monaco Language Service
|
|
2665
3317
|
-----------------------
|
|
2666
3318
|
|
|
@@ -2722,9 +3374,11 @@ when the editor is torn down.
|
|
|
2722
3374
|
| `compiler` | object | — | **Required.** The `window.RapydScript` compiler bundle. |
|
|
2723
3375
|
| `parseDelay` | number | `300` | Debounce delay (ms) before re-checking after an edit. |
|
|
2724
3376
|
| `virtualFiles` | `{name: source}` | `{}` | Virtual modules available to `import` statements. |
|
|
3377
|
+
| `stdlibFiles` | `{name: source}` | `{}` | Like `virtualFiles` but treated as stdlib — always available and never produce bad-import warnings. |
|
|
2725
3378
|
| `dtsFiles` | `[{name, content}]` | `[]` | TypeScript `.d.ts` files loaded at startup. |
|
|
2726
3379
|
| `loadDts` | `(name) => Promise<string>` | — | Async callback for lazy-loading `.d.ts` content on demand. |
|
|
2727
3380
|
| `extraBuiltins` | `{name: true}` | `{}` | Extra global names that suppress undefined-symbol warnings. |
|
|
3381
|
+
| `pythonFlags` | string | — | Comma-separated Python flags to enable globally (e.g. `"dict_literals,overload_getitem"`). See [Python Flags](#python-flags) above. |
|
|
2728
3382
|
|
|
2729
3383
|
### Runtime API
|
|
2730
3384
|
|
|
@@ -2744,6 +3398,9 @@ service.loadDts('lib.dom').then(function () { console.log('DOM types loaded'); }
|
|
|
2744
3398
|
// Suppress undefined-symbol warnings for additional global names
|
|
2745
3399
|
service.addGlobals(['myFrameworkGlobal', '$']);
|
|
2746
3400
|
|
|
3401
|
+
// Get the most recently built scope map for a Monaco model (null if not yet analysed)
|
|
3402
|
+
var scopeMap = service.getScopeMap(editorModel);
|
|
3403
|
+
|
|
2747
3404
|
// Tear down all Monaco providers and event listeners
|
|
2748
3405
|
service.dispose();
|
|
2749
3406
|
```
|
|
@@ -2867,6 +3524,13 @@ original `.py` file with working breakpoints and correct error stack frames.
|
|
|
2867
3524
|
| `keep_docstrings` | bool | `false` | Keep docstrings in the output. |
|
|
2868
3525
|
| `js_version` | number | `6` | Target ECMAScript version (5 or 6). |
|
|
2869
3526
|
| `private_scope` | bool | `false` | Wrap the output in an IIFE. |
|
|
3527
|
+
| `python_flags` | string | — | Comma-separated Python flags to enable for this compilation (e.g. `"dict_literals,overload_operators"`). See [Python Flags](#python-flags) above. Flags set here override any inherited from a previous `compile()` call on a streaming compiler. |
|
|
3528
|
+
| `virtual_files` | `{name: source}` | — | Map of module-name → RapydScript source for modules importable via `import`. Only used when the underlying streaming compiler was created with a virtual-file context (as `web_repl()` does). |
|
|
3529
|
+
| `discard_asserts` | bool | `false` | Strip all `assert` statements from the output. |
|
|
3530
|
+
| `omit_function_metadata` | bool | `false` | Omit per-function metadata (e.g. argument names) from the output for smaller bundles. |
|
|
3531
|
+
| `write_name` | bool | `false` | Emit a `var __name__ = "…"` assignment at the top of the output. |
|
|
3532
|
+
| `tree_shake` | bool | `false` | Remove unused imported names from the output (requires stdlib imports). |
|
|
3533
|
+
| `filename` | string | `'<input>'` | Source filename embedded in the source map and used in error messages. |
|
|
2870
3534
|
|
|
2871
3535
|
**How it works**
|
|
2872
3536
|
|