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
@@ -1,31 +1,33 @@
1
1
  {
2
- "ast": "7a1a1800d9ee7af7f7153eee38002e4e9dcfb71e",
3
- "baselib-builtins": "50927b38fded9bd9dbe14c42a20dd8e930ac021f",
4
- "baselib-containers": "f7ac21a4dfc6311693239ea1eb45e74fae45a3f5",
5
- "baselib-errors": "f2423e1e2489bdd7fb8c8725bb76436898c8008c",
6
- "baselib-internal": "1b77d40970a8ef2d886132dc7c21c9510d2eb4cd",
7
- "baselib-itertools": "ab1f3257642c8d26fab1ff9d392814a459a60cdb",
8
- "baselib-str": "8c396e4fae02ae34b6d3d805becf7bfdd36625ee",
9
- "compiler": "cfbfceb0439fed3302f78d80b303dca713b25e7b",
10
- "errors": "d1b33848d19b141e19cc079cf78421f29b6d2c05",
11
- "output/__init__": "da39a3ee5e6b4b0d3255bfef95601890afd80709",
12
- "output/classes": "d05c1992cc91b337a4e4ff137b0aa3d626e6624b",
13
- "output/codegen": "0519a88c2704fe60b98fe747ca39f6be43b9abf3",
14
- "output/comments": "78ec38d8b34da96c078653e2d0d4049d7003906b",
15
- "output/exceptions": "c7d90155694c7108e94d0940a160ae83725421d7",
16
- "output/functions": "abaa81b171359eb77be6ea87cbdf9d7421d4622b",
17
- "output/literals": "fdbfb744fec8dfea1e1c62cb49767c60160fd402",
18
- "output/loops": "f59cc623320f57edb01953f7877d712758e9f825",
19
- "output/modules": "bd3e3f3f6794fb6e401867b4d011c4e3aab98893",
20
- "output/operators": "f8142836a13b75680cb4874391db9e871fad0cad",
21
- "output/statements": "7d8dfdc0b43e3e430be7ce3b23ffaf1b41408d8c",
22
- "output/stream": "46375cb467477ac898546e818bfdfa5be738c352",
23
- "output/utils": "595968f96f6fdcc51eb41c34d64c92bb595e3cb1",
24
- "parse": "d5c1a77662dfcff841dfcd368d5dbb129a592f5d",
25
- "string_interpolation": "bff1cc76d772d24d35707f6c794f38734ca08376",
26
- "tokenizer": "00fc24a41edac9f9b31735e6290348005a623cef",
27
- "unicode_aliases": "79ac6eaa5e6be44a5397d62c561f854a8fe7528e",
28
- "utils": "c1666db819aa7c8db38697e34e18362e3cb45869",
29
- "#compiler#": "d98fcbb15d08dae74d9c7371ea28fea676642e67",
30
- "#compiled_with#": "d98fcbb15d08dae74d9c7371ea28fea676642e67"
2
+ "ast": "c8f6f1be6f7f73b1b9e2bbf470f5e2e5fff879df",
3
+ "baselib-builtins": "ced189b19392b1f425a1a180b90bc61e5e1b022f",
4
+ "baselib-containers": "d2f534e6530dfb309b074bf7fac082c65779e778",
5
+ "baselib-errors": "a9e8c63e450360fd0bd70642d4c107672d395ccf",
6
+ "baselib-internal": "b020b5154a7ee023ceb5852bf35eeee31e285d87",
7
+ "baselib-itertools": "425f5c45bbd5de894cae891e71ba1a9e9e2063d5",
8
+ "baselib-str": "a00bdd267521d31d97cdc76581f955b6fafb4bae",
9
+ "compiler": "bb16e915c60dc4ffb5bfe98bef411736d19fa297",
10
+ "errors": "257eca38b6de987e5fd80672bec9b9981847e1bd",
11
+ "output\\classes": "a88c3c84ded9049d7a5052fb151d51bdbb600dcd",
12
+ "output\\codegen": "69151b2cd53ff8b3270a122c65e1a0f56735150e",
13
+ "output\\comments": "63b39620f9d6f407aa2d4ddb557d1c60ef296b05",
14
+ "output\\exceptions": "e7d9119550403e6c5730d40b9bc9c923a23d6eb7",
15
+ "output\\functions": "58972ccc4562ab3422317f79f68ea3e00b765279",
16
+ "output\\jsx": "14f32c048301965de7764c5b74b651bc279de937",
17
+ "output\\literals": "287ec4222c79f1ebfa2c6efae925e794cbb931ab",
18
+ "output\\loops": "93afeea09e81382edf1c2f6009f4811430d0ebb8",
19
+ "output\\modules": "15735b9b07260d11ba231fc3439818bd1a54947e",
20
+ "output\\operators": "d9ebb70a00cfe6be60c5d75596edf7986f619644",
21
+ "output\\statements": "94ee0cd084f22aea451b96eb1a9a831084cc4267",
22
+ "output\\stream": "2723d80bc398468e0828f50fb0837095c52f45dc",
23
+ "output\\treeshake": "4a490ba097739d924db9e3cd9eb7718db5e24cae",
24
+ "output\\utils": "e957919bfccb9a3ab510d824a8f2ee3fc2689795",
25
+ "output\\__init__": "da39a3ee5e6b4b0d3255bfef95601890afd80709",
26
+ "parse": "1815f278b2b974ed79973f792a4dbcccfb35c2b8",
27
+ "string_interpolation": "88dce6c2c5ee75126a6838a1506841c6531a0d15",
28
+ "tokenizer": "6c06a87951cc4cfe6256dfa4f22ab3533967e856",
29
+ "unicode_aliases": "7fbcbc9c24adcb2e33fac8d69aaafe5047fcc2c2",
30
+ "utils": "35a2a707c841da851e18c64edac54e7c20b7dfc9",
31
+ "#compiler#": "724970153770773cd9e1ff1e588f17df9c607ee9",
32
+ "#compiled_with#": "724970153770773cd9e1ff1e588f17df9c607ee9"
31
33
  }
package/session.vim CHANGED
@@ -1,4 +1,4 @@
1
- set wildignore+=*.pyj-cached
2
- set wildignore+=node_modules
3
- imap <F4> ρσ_
4
- cmap <F4> ρσ_
1
+ set wildignore+=*.pyj-cached
2
+ set wildignore+=node_modules
3
+ imap <F4> ρσ_
4
+ cmap <F4> ρσ_
package/setup.cfg CHANGED
@@ -1,2 +1,2 @@
1
- [rapydscript]
2
- globals=assert,RapydScript
1
+ [rapydscript]
2
+ globals=assert,RapydScript
package/src/ast.pyj CHANGED
@@ -600,6 +600,9 @@ class AST_Class(AST_Scope):
600
600
  'statements': "[AST_Node*] list of statements in the class scope (excluding method definitions)",
601
601
  'dynamic_properties': '[dict] map of dynamic property names to property descriptors of the form {getter:AST_Method, setter:AST_Method',
602
602
  'classvars': '[dict] map containing all class variables as keys, to be used to easily test for existence of a class variable',
603
+ 'has_new': "[boolean] true if the class defines a __new__ method",
604
+ 'has_attr_dunders': "[boolean] true if the class defines any of __getattr__/__setattr__/__delattr__/__getattribute__",
605
+ 'class_kwargs': "[array] keyword arguments from class header (e.g. class C(Base, key=val):) as [[key_node, value_node], ...]",
603
606
  }
604
607
 
605
608
  def _walk(self, visitor):
@@ -610,6 +613,9 @@ class AST_Class(AST_Scope):
610
613
  self.name._walk(visitor)
611
614
  walk_body(self, visitor)
612
615
  if (self.parent) self.parent._walk(visitor)
616
+ if self.class_kwargs:
617
+ for kw in self.class_kwargs:
618
+ kw[1]._walk(visitor)
613
619
  )
614
620
 
615
621
  class AST_Method(AST_Lambda):
@@ -725,7 +731,8 @@ class AST_Except(AST_Block):
725
731
  "An `except` node for RapydScript, which resides inside the catch block"
726
732
  properties = {
727
733
  'argname': "[AST_SymbolCatch] symbol for the exception",
728
- 'errors': "[AST_SymbolVar*] error classes to catch in this block"
734
+ 'errors': "[AST_SymbolVar*] error classes to catch in this block",
735
+ 'is_star': '[bool] True for except* (exception group) clauses',
729
736
  }
730
737
 
731
738
  def _walk(self, visitor):
@@ -1161,6 +1168,17 @@ class AST_ObjectSpread(AST_Node):
1161
1168
  self.value._walk(visitor)
1162
1169
  )
1163
1170
 
1171
+ class AST_Spread(AST_Node):
1172
+ "A *expr spread item inside a list or set literal: [1, *a, 2]"
1173
+ properties = {
1174
+ 'expression': "[AST_Node] the expression being spread",
1175
+ }
1176
+
1177
+ def _walk(self, visitor):
1178
+ return visitor._visit(self, def():
1179
+ self.expression._walk(visitor)
1180
+ )
1181
+
1164
1182
  class AST_Set(AST_Node):
1165
1183
  "A set literal"
1166
1184
  properties = {
@@ -1360,6 +1378,80 @@ class TreeWalker:
1360
1378
  self = p
1361
1379
  # }}}
1362
1380
 
1381
+ # JSX nodes {{{
1382
+
1383
+ class AST_JSXElement(AST_Node):
1384
+ "A JSX element like <div>...</div> or <Component />"
1385
+ properties = {
1386
+ 'tag': "[string] The tag name (e.g. 'div', 'MyComponent')",
1387
+ 'props': "[AST_JSXAttribute[]] The props/attributes",
1388
+ 'children': "[AST_Node[]] The children",
1389
+ 'self_closing': "[bool] Whether self-closing (no children)"
1390
+ }
1391
+
1392
+ def _walk(self, visitor):
1393
+ return visitor._visit(self, def():
1394
+ for prop in self.props:
1395
+ prop._walk(visitor)
1396
+ for child in self.children:
1397
+ child._walk(visitor)
1398
+ )
1399
+
1400
+ class AST_JSXFragment(AST_Node):
1401
+ "A JSX fragment <>...</>"
1402
+ properties = {
1403
+ 'children': "[AST_Node[]] The children"
1404
+ }
1405
+
1406
+ def _walk(self, visitor):
1407
+ return visitor._visit(self, def():
1408
+ for child in self.children:
1409
+ child._walk(visitor)
1410
+ )
1411
+
1412
+ class AST_JSXAttribute(AST_Node):
1413
+ "A JSX attribute like prop='val', prop={expr}, or just prop (boolean)"
1414
+ properties = {
1415
+ 'name': "[string] The attribute name",
1416
+ 'value': "[AST_Node|null] The value (null for boolean attrs)"
1417
+ }
1418
+
1419
+ def _walk(self, visitor):
1420
+ return visitor._visit(self, def():
1421
+ if self.value:
1422
+ self.value._walk(visitor)
1423
+ )
1424
+
1425
+ class AST_JSXSpread(AST_Node):
1426
+ "A JSX spread attribute {...expr}"
1427
+ properties = {
1428
+ 'expression': "[AST_Node] The spread expression"
1429
+ }
1430
+
1431
+ def _walk(self, visitor):
1432
+ return visitor._visit(self, def():
1433
+ self.expression._walk(visitor)
1434
+ )
1435
+
1436
+ class AST_JSXText(AST_Node):
1437
+ "Text content inside a JSX element"
1438
+ properties = {
1439
+ 'value': "[string] The text content"
1440
+ }
1441
+
1442
+ class AST_JSXExprContainer(AST_Node):
1443
+ "A JSX expression container {expr}"
1444
+ properties = {
1445
+ 'expression': "[AST_Node] The expression"
1446
+ }
1447
+
1448
+ def _walk(self, visitor):
1449
+ return visitor._visit(self, def():
1450
+ self.expression._walk(visitor)
1451
+ )
1452
+
1453
+ # }}}
1454
+
1363
1455
  class Found(Exception):
1364
1456
  pass
1365
1457
 
@@ -20,6 +20,7 @@ def ρσ_bool(val):
20
20
  v'if ((typeof Set === "function" && val instanceof Set) || (typeof Map === "function" && val instanceof Map)) return val.size > 0'
21
21
  v'if (!val.constructor || val.constructor === Object) return Object.keys(val).length > 0'
22
22
  return True
23
+ ρσ_bool.__name__ = 'bool'
23
24
 
24
25
  def ρσ_print(*args, **kwargs):
25
26
  if v'typeof console' is 'object':
@@ -35,6 +36,7 @@ def ρσ_int(val, base):
35
36
  if isNaN(ans):
36
37
  raise ValueError('Invalid literal for int with base ' + (base or 10) + ': ' + val)
37
38
  return ans
39
+ ρσ_int.__name__ = 'int'
38
40
 
39
41
  def ρσ_float(val):
40
42
  if jstype(val) is "number":
@@ -44,6 +46,7 @@ def ρσ_float(val):
44
46
  if isNaN(ans):
45
47
  raise ValueError('Could not convert string to float: ' + arguments[0])
46
48
  return ans
49
+ ρσ_float.__name__ = 'float'
47
50
 
48
51
  def ρσ_arraylike_creator():
49
52
  names = 'Int8Array Uint8Array Uint8ClampedArray Int16Array Uint16Array Int32Array Uint32Array Float32Array Float64Array'.split(' ')
@@ -282,6 +285,23 @@ def ρσ_hasattr(obj, name):
282
285
  def ρσ_get_module(name):
283
286
  return ρσ_modules[name]
284
287
 
288
+ def ρσ__import__(name, globals, locals, fromlist, level):
289
+ # Return the module from the already-compiled ρσ_modules registry.
290
+ # Like Python: without fromlist (or empty fromlist) returns the top-level
291
+ # package; with a non-empty fromlist returns the named (possibly dotted) module.
292
+ # NOTE: the module must have been statically imported elsewhere in the source;
293
+ # __import__ only provides a runtime reference to an already-compiled module.
294
+ if v'typeof ρσ_modules' is 'undefined':
295
+ raise ImportError('No module named \'' + name + '\'')
296
+ if fromlist is not undefined and fromlist is not None and fromlist.length:
297
+ lookup = name
298
+ else:
299
+ lookup = name.split('.')[0]
300
+ module = ρσ_modules[lookup]
301
+ if module is undefined:
302
+ raise ModuleNotFoundError('No module named \'' + lookup + '\'')
303
+ return module
304
+
285
305
  def ρσ_pow(x, y, z):
286
306
  ans = Math.pow(x, y)
287
307
  if z is not undefined:
@@ -322,6 +342,7 @@ def ρσ_hash(obj):
322
342
  }
323
343
  return ρσ_h;
324
344
  }'''
345
+ v'if (obj.__hash__ === null) throw new TypeError("unhashable type: \'" + (obj.constructor && obj.constructor.name ? obj.constructor.name : "object") + "\'")'
325
346
  v'if (typeof obj.__hash__ === "function") return obj.__hash__()'
326
347
  v'if (Array.isArray(obj)) throw new TypeError("unhashable type: \'list\'")'
327
348
  v'if (typeof ρσ_set === "function" && obj instanceof ρσ_set) throw new TypeError("unhashable type: \'set\'")'
@@ -440,7 +461,7 @@ class ρσ_slice:
440
461
 
441
462
  v'var abs = Math.abs, max = ρσ_max.bind(Math.max), min = ρσ_max.bind(Math.min), bool = ρσ_bool, type = ρσ_type'
442
463
  v'var float = ρσ_float, int = ρσ_int, arraylike = ρσ_arraylike_creator(), ρσ_arraylike = arraylike'
443
- v'var id = ρσ_id, get_module = ρσ_get_module, pow = ρσ_pow, divmod = ρσ_divmod'
464
+ v'var id = ρσ_id, get_module = ρσ_get_module, pow = ρσ_pow, divmod = ρσ_divmod, __import__ = ρσ__import__'
444
465
  v'var dir = ρσ_dir, ord = ρσ_ord, chr = ρσ_chr, bin = ρσ_bin, hex = ρσ_hex, callable = ρσ_callable, round = ρσ_round'
445
466
  v'var enumerate = ρσ_enumerate, iter = ρσ_iter, reversed = ρσ_reversed, len = ρσ_len'
446
467
  v'var range = ρσ_range, getattr = ρσ_getattr, setattr = ρσ_setattr, hasattr = ρσ_hasattr, issubclass = ρσ_issubclass, hash = ρσ_hash, next = ρσ_next'
@@ -243,6 +243,26 @@ def sorted(iterable, key=None, reverse=False):
243
243
  return ans
244
244
  # }}}
245
245
 
246
+ # tuple {{{
247
+ def ρσ_tuple_constructor(iterable):
248
+ if iterable is undefined:
249
+ return v'[]'
250
+ if ρσ_arraylike(iterable):
251
+ return Array.prototype.slice.call(iterable)
252
+ if jstype(iterable[ρσ_iterator_symbol]) is 'function':
253
+ iterator = iterable.keys() if jstype(Map) is 'function' and v'iterable instanceof Map' else iterable[ρσ_iterator_symbol]()
254
+ ans = []
255
+ result = iterator.next()
256
+ while not result.done:
257
+ ans.push(result.value)
258
+ result = iterator.next()
259
+ return ans
260
+ return Object.keys(iterable)
261
+
262
+ ρσ_tuple_constructor.__name__ = 'tuple'
263
+ v'var tuple = ρσ_tuple_constructor'
264
+ # }}}
265
+
246
266
  # set {{{
247
267
  v'var ρσ_global_object_id = 0, ρσ_set_implementation'
248
268
 
@@ -698,6 +718,12 @@ def ρσ_dict_polyfill():
698
718
  return v"{'done':false, 'value':this._s[this._keys[this._i]]}"
699
719
  return ans
700
720
 
721
+ ρσ_dict_polyfill.prototype.forEach = def(callback):
722
+ keys = Object.keys(this._store)
723
+ for v'var ρσ_fi = 0; ρσ_fi < keys.length; ρσ_fi++':
724
+ entry = this._store[keys[v'ρσ_fi']]
725
+ callback(entry[1], entry[0], this)
726
+
701
727
  if jstype(Map) is not 'function' or jstype(Map.prototype.delete) is not 'function':
702
728
  v'ρσ_dict_implementation = ρσ_dict_polyfill'
703
729
  else:
@@ -862,6 +888,15 @@ Object.defineProperties(ρσ_dict.prototype, {
862
888
  r = iterator.next()
863
889
  return ans
864
890
 
891
+ ρσ_dict.prototype.toJSON = def():
892
+ ans = {}
893
+ iterator = this.jsmap.entries()
894
+ r = iterator.next()
895
+ while not r.done:
896
+ ans[r.value[0]] = r.value[1]
897
+ r = iterator.next()
898
+ return ans
899
+
865
900
  def ρσ_dict_wrap(x):
866
901
  ans = new ρσ_dict()
867
902
  ans.jsmap = x
@@ -869,4 +904,68 @@ def ρσ_dict_wrap(x):
869
904
 
870
905
  v'var dict = ρσ_dict, dict_wrap = ρσ_dict_wrap'
871
906
 
907
+ v'''
908
+ function ρσ_kwargs_to_dict(kw) {
909
+ // Augment the plain kwargs object with non-enumerable Python dict methods so
910
+ // that kw.items(), kw.keys(), kw.values() work in user code, while plain
911
+ // property access (kw.propname) and Object.keys(kw) are unaffected.
912
+ //
913
+ // items/keys/values return dual-mode arrays: they support both Array indexing
914
+ // (for ρσ_dict.prototype.update which does pairs[i]) and iterator protocol
915
+ // (for `for k, v in kw.items():` which calls .next()).
916
+ function _make_seq(arr) {
917
+ arr._ρσ_i = 0;
918
+ arr.next = function() {
919
+ return this._ρσ_i < this.length
920
+ ? {done: false, value: this[this._ρσ_i++]}
921
+ : {done: true, value: undefined};
922
+ };
923
+ arr[ρσ_iterator_symbol] = function() { this._ρσ_i = 0; return this; };
924
+ return arr;
925
+ }
926
+ function _def(name, fn) {
927
+ if (!Object.prototype.hasOwnProperty.call(kw, name)) {
928
+ Object.defineProperty(kw, name, {value: fn, configurable: true, writable: true, enumerable: false});
929
+ }
930
+ }
931
+ _def("items", function() {
932
+ var ks = Object.keys(kw), arr = [], i;
933
+ for (i = 0; i < ks.length; i++) arr.push([ks[i], kw[ks[i]]]);
934
+ return _make_seq(arr);
935
+ });
936
+ _def("entries", kw.items);
937
+ _def("keys", function() {
938
+ return _make_seq(Object.keys(kw).slice());
939
+ });
940
+ _def("values", function() {
941
+ var ks = Object.keys(kw), arr = [], i;
942
+ for (i = 0; i < ks.length; i++) arr.push(kw[ks[i]]);
943
+ return _make_seq(arr);
944
+ });
945
+ _def("get", function(k, d) {
946
+ return Object.prototype.hasOwnProperty.call(kw, k) ? kw[k] : (d !== undefined ? d : null);
947
+ });
948
+ _def("__contains__", function(k) { return Object.prototype.hasOwnProperty.call(kw, k); });
949
+ _def("has", function(k) { return Object.prototype.hasOwnProperty.call(kw, k); });
950
+ _def("__len__", function() { return Object.keys(kw).length; });
951
+ kw[ρσ_iterator_symbol] = function() {
952
+ var ks = Object.keys(kw), i = 0;
953
+ return {next: function() {
954
+ return i < ks.length ? {done: false, value: ks[i++]} : {done: true, value: undefined};
955
+ }};
956
+ };
957
+ return kw;
958
+ }
959
+ '''
960
+
961
+ v"""var ρσ_json_parse = function(text, reviver) {
962
+ function dict_reviver(key, value) {
963
+ if (value !== null && typeof value === "object" && !Array.isArray(value) && !(value instanceof ρσ_dict)) {
964
+ value = ρσ_dict(value);
965
+ }
966
+ return reviver ? reviver.call(this, key, value) : value;
967
+ }
968
+ return JSON.parse(text, dict_reviver);
969
+ };"""
970
+
872
971
  # }}}
@@ -38,3 +38,47 @@ class ZeroDivisionError(Exception):
38
38
 
39
39
  class StopIteration(Exception):
40
40
  pass
41
+
42
+ class ImportError(Exception):
43
+ pass
44
+
45
+ class ModuleNotFoundError(ImportError):
46
+ pass
47
+
48
+ def _is_exc_class(obj):
49
+ # True when obj is an Error subclass (or Error itself), not a plain predicate function
50
+ return jstype(obj) is 'function' and (obj is Error or (obj.prototype and isinstance(obj.prototype, Error)))
51
+
52
+
53
+ class ExceptionGroup(Exception):
54
+
55
+ def __init__(self, message, exceptions):
56
+ Exception.__init__(self, message)
57
+ self.exceptions = exceptions if exceptions else []
58
+
59
+ def subgroup(self, condition):
60
+ if _is_exc_class(condition):
61
+ matched = [e for e in self.exceptions if isinstance(e, condition)]
62
+ elif callable(condition):
63
+ matched = [e for e in self.exceptions if condition(e)]
64
+ else:
65
+ matched = [e for e in self.exceptions if isinstance(e, condition)]
66
+ return ExceptionGroup(self.message, matched) if matched else None
67
+
68
+ def split(self, condition):
69
+ if _is_exc_class(condition):
70
+ matched = [e for e in self.exceptions if isinstance(e, condition)]
71
+ rest = [e for e in self.exceptions if not isinstance(e, condition)]
72
+ elif callable(condition):
73
+ matched = [e for e in self.exceptions if condition(e)]
74
+ rest = [e for e in self.exceptions if not condition(e)]
75
+ else:
76
+ matched = [e for e in self.exceptions if isinstance(e, condition)]
77
+ rest = [e for e in self.exceptions if not isinstance(e, condition)]
78
+ return [
79
+ ExceptionGroup(self.message, matched) if matched else None,
80
+ ExceptionGroup(self.message, rest) if rest else None
81
+ ]
82
+
83
+ def __repr__(self):
84
+ return 'ExceptionGroup(' + repr(self.message) + ', ' + repr(self.exceptions) + ')'
@@ -87,6 +87,14 @@ def ρσ_extends(child, parent):
87
87
  child.prototype.constructor = child
88
88
  Object.setPrototypeOf(child, parent)
89
89
 
90
+ def ρσ_object_new(cls):
91
+ return v'Object.create(cls.prototype)'
92
+
93
+ def ρσ_new(parent, cls):
94
+ if parent and jstype(parent.__new__) is 'function':
95
+ return parent.__new__.apply(parent, v'Array.prototype.slice.call(arguments, 1)')
96
+ return v'Object.create(cls.prototype)'
97
+
90
98
  ρσ_in = (def ():
91
99
  if jstype(Map) is 'function' and jstype(Set) is 'function':
92
100
  return def(val, arr):
@@ -131,15 +139,23 @@ def ρσ_Iterable(iterable):
131
139
  ans = Object.create(None)
132
140
  ans[ρσ_kwargs_symbol] = True
133
141
  for v'var i = 0; i < arguments.length; i++':
134
- Object.assign(ans, arguments[i])
142
+ arg = arguments[i]
143
+ if v'arg && arg.jsmap && typeof arg.jsmap.forEach === "function"':
144
+ v'arg.jsmap.forEach(function(v, k) { ans[k] = v; })'
145
+ else:
146
+ Object.assign(ans, arg)
135
147
  return ans
136
148
  return def():
137
149
  ans = Object.create(None)
138
150
  ans[ρσ_kwargs_symbol] = True
139
151
  for v'var i = 0; i < arguments.length; i++':
140
- keys = Object.keys(arguments[i])
141
- for v'var j = 0; j < keys.length; j++':
142
- ans[keys[j]] = arguments[i][keys[j]]
152
+ arg = arguments[i]
153
+ if v'arg && arg.jsmap && typeof arg.jsmap.forEach === "function"':
154
+ v'arg.jsmap.forEach(function(v, k) { ans[k] = v; })'
155
+ else:
156
+ keys = Object.keys(arg)
157
+ for v'var j = 0; j < keys.length; j++':
158
+ ans[keys[j]] = arg[keys[j]]
143
159
  return ans
144
160
  )()
145
161
 
@@ -177,6 +193,8 @@ def ρσ_interpolate_kwargs_constructor(apply, f, supplied_args):
177
193
  return this
178
194
 
179
195
  def ρσ_getitem(obj, key):
196
+ if v'typeof obj === "function"' and obj.__class_getitem__:
197
+ return obj.__class_getitem__(key)
180
198
  if obj.__getitem__:
181
199
  return obj.__getitem__(key)
182
200
  if v'typeof ρσ_slice !== "undefined" && key instanceof ρσ_slice':
@@ -458,3 +476,75 @@ def ρσ_instanceof():
458
476
  break
459
477
  cls = p.constructor
460
478
  return False
479
+
480
+ # ── Attribute-dunder support (__getattr__ / __setattr__ / __delattr__ / __getattribute__) ──
481
+ # We use a JavaScript Proxy to intercept attribute access/assignment/deletion on class instances
482
+ # that define any of the four attribute dunders.
483
+
484
+ # Cache the JS Proxy constructor with a ρσ_ name to avoid collisions with user-defined 'Proxy' classes.
485
+ ρσ_JS_Proxy = v'typeof Proxy === "function" ? Proxy : null'
486
+
487
+ # Symbol (or fallback string key) used to retrieve the raw underlying target from a wrapped proxy.
488
+ ρσ_proxy_target_symbol = v'typeof Symbol === "function" ? Symbol("ρσ_proxy_target") : "__ρσ_proxy_target__"'
489
+
490
+ ρσ_attr_proxy_handler = {
491
+ 'get': def(target, prop, receiver):
492
+ # Always expose the raw target via the sentinel key (used by ρσ_object_* helpers).
493
+ if prop is ρσ_proxy_target_symbol:
494
+ return target
495
+ # Pass through JS symbols (Symbol.iterator, Symbol.toPrimitive, etc.) unchanged.
496
+ if jstype(prop) is 'symbol':
497
+ return v'Reflect.get(target, prop, receiver)'
498
+ # __getattribute__ overrides every attribute lookup (except itself, to avoid infinite recursion).
499
+ if jstype(target.__getattribute__) is 'function' and prop is not '__getattribute__':
500
+ try:
501
+ return target.__getattribute__.call(receiver, prop)
502
+ except AttributeError:
503
+ # AttributeError from __getattribute__ → try __getattr__ fallback.
504
+ if jstype(target.__getattr__) is 'function':
505
+ return target.__getattr__.call(receiver, prop)
506
+ raise
507
+ # Normal property lookup via prototype chain.
508
+ val = v'Reflect.get(target, prop, receiver)'
509
+ # __getattr__ is only called when the attribute is genuinely missing.
510
+ if val is undefined and jstype(target.__getattr__) is 'function' and not v'(prop in target)':
511
+ return target.__getattr__.call(receiver, prop)
512
+ return val
513
+ ,
514
+ 'set': def(target, prop, value, receiver):
515
+ if jstype(target.__setattr__) is 'function':
516
+ target.__setattr__.call(receiver, prop, value)
517
+ return True
518
+ # Pass 'target' as receiver (not proxy) to avoid infinite recursion through the Proxy set trap.
519
+ return v'Reflect.set(target, prop, value, target)'
520
+ ,
521
+ 'deleteProperty': def(target, prop):
522
+ if jstype(target.__delattr__) is 'function':
523
+ # deleteProperty has no receiver; pass target as 'this'.
524
+ # Inside __delattr__, use ρσ_object_delattr(self, name) for a direct delete.
525
+ target.__delattr__.call(target, prop)
526
+ return True
527
+ return v'Reflect.deleteProperty(target, prop)'
528
+ }
529
+
530
+ def ρσ_object_setattr(obj, name, value):
531
+ # Bypass __setattr__ and set directly on the underlying object.
532
+ # Use this inside __setattr__ to avoid infinite recursion (like object.__setattr__ in Python).
533
+ target = obj[ρσ_proxy_target_symbol]
534
+ if target is undefined:
535
+ target = obj
536
+ v'target[name] = value'
537
+
538
+ def ρσ_object_getattr(obj, name):
539
+ # Bypass __getattribute__ and read directly from the underlying object.
540
+ target = obj[ρσ_proxy_target_symbol]
541
+ if target is undefined:
542
+ target = obj
543
+ return target[name]
544
+
545
+ def ρσ_object_delattr(obj, name):
546
+ # Bypass __delattr__ and delete directly from the underlying object.
547
+ target = obj[ρσ_proxy_target_symbol]
548
+ if target is undefined:
549
+ target = obj
550
+ v'delete target[name]'