reactpy 2.0.0b5__tar.gz → 2.0.0b6__tar.gz

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 (143) hide show
  1. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/.gitignore +1 -1
  2. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/PKG-INFO +1 -1
  3. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/pyproject.toml +2 -7
  4. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/build_scripts/clean_js_dir.py +12 -11
  5. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/__init__.py +3 -2
  6. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/_html.py +11 -9
  7. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/core/_life_cycle_hook.py +4 -1
  8. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/core/layout.py +43 -38
  9. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/core/serve.py +11 -16
  10. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/core/vdom.py +3 -5
  11. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/pyscript/utils.py +1 -1
  12. reactpy-2.0.0b6/src/reactpy/reactjs/__init__.py +353 -0
  13. reactpy-2.0.0b6/src/reactpy/reactjs/module.py +203 -0
  14. reactpy-2.0.0b6/src/reactpy/reactjs/types.py +7 -0
  15. reactpy-2.0.0b6/src/reactpy/reactjs/utils.py +183 -0
  16. reactpy-2.0.0b6/src/reactpy/static/index-h31022cd.js +5 -0
  17. reactpy-2.0.0b6/src/reactpy/static/index-h31022cd.js.map +11 -0
  18. reactpy-2.0.0b6/src/reactpy/static/index-sbddj6ms.js +5 -0
  19. reactpy-2.0.0b6/src/reactpy/static/index-sbddj6ms.js.map +10 -0
  20. reactpy-2.0.0b6/src/reactpy/static/index-y71bxs88.js +5 -0
  21. reactpy-2.0.0b6/src/reactpy/static/index-y71bxs88.js.map +10 -0
  22. reactpy-2.0.0b6/src/reactpy/static/index.js +4 -0
  23. reactpy-2.0.0b6/src/reactpy/static/index.js.map +18 -0
  24. reactpy-2.0.0b6/src/reactpy/static/react-dom.js +4 -0
  25. reactpy-2.0.0b6/src/reactpy/static/react-dom.js.map +11 -0
  26. reactpy-2.0.0b6/src/reactpy/static/react-jsx-runtime.js +4 -0
  27. reactpy-2.0.0b6/src/reactpy/static/react-jsx-runtime.js.map +9 -0
  28. reactpy-2.0.0b6/src/reactpy/static/react.js +4 -0
  29. reactpy-2.0.0b6/src/reactpy/static/react.js.map +10 -0
  30. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/testing/backend.py +4 -4
  31. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/testing/display.py +2 -1
  32. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/testing/logs.py +1 -1
  33. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/transforms.py +2 -2
  34. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/types.py +17 -11
  35. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/utils.py +1 -1
  36. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/web/__init__.py +0 -6
  37. reactpy-2.0.0b6/src/reactpy/web/module.py +130 -0
  38. reactpy-2.0.0b6/src/reactpy/web/utils.py +3 -0
  39. reactpy-2.0.0b5/src/reactpy/static/index.js +0 -4
  40. reactpy-2.0.0b5/src/reactpy/static/index.js.map +0 -22
  41. reactpy-2.0.0b5/src/reactpy/web/module.py +0 -566
  42. reactpy-2.0.0b5/src/reactpy/web/templates/react.js +0 -61
  43. reactpy-2.0.0b5/src/reactpy/web/utils.py +0 -159
  44. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/LICENSE +0 -0
  45. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/README.md +0 -0
  46. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/build_scripts/copy_dir.py +0 -0
  47. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/js/.gitignore +0 -0
  48. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/js/bun.lockb +0 -0
  49. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/js/eslint.config.mjs +0 -0
  50. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/js/package.json +0 -0
  51. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/js/tsconfig.json +0 -0
  52. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/_console/__init__.py +0 -0
  53. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/_console/ast_utils.py +0 -0
  54. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/_console/cli.py +0 -0
  55. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/_console/rewrite_keys.py +0 -0
  56. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/_console/rewrite_props.py +0 -0
  57. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/_option.py +0 -0
  58. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/_warnings.py +0 -0
  59. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/config.py +0 -0
  60. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/core/__init__.py +0 -0
  61. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/core/_f_back.py +0 -0
  62. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/core/_thread_local.py +0 -0
  63. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/core/component.py +0 -0
  64. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/core/events.py +0 -0
  65. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/core/hooks.py +0 -0
  66. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/executors/__init__.py +0 -0
  67. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/executors/asgi/__init__.py +0 -0
  68. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/executors/asgi/middleware.py +0 -0
  69. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/executors/asgi/pyscript.py +0 -0
  70. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/executors/asgi/standalone.py +0 -0
  71. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/executors/asgi/types.py +0 -0
  72. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/executors/utils.py +0 -0
  73. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/logging.py +0 -0
  74. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/py.typed +0 -0
  75. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/pyscript/__init__.py +0 -0
  76. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/pyscript/component_template.py +0 -0
  77. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/pyscript/components.py +0 -0
  78. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/pyscript/layout_handler.py +0 -0
  79. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/morphdom/morphdom-esm.js +0 -0
  80. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/morphdom/morphdom-factory.js +0 -0
  81. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/morphdom/morphdom-umd.js +0 -0
  82. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/morphdom/morphdom-umd.min.js +0 -0
  83. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/morphdom/morphdom.js +0 -0
  84. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/pyscript/codemirror-BYspKCDy.js +0 -0
  85. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/pyscript/codemirror-BYspKCDy.js.map +0 -0
  86. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/pyscript/codemirror_commands-BLDaEdQ6.js +0 -0
  87. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/pyscript/codemirror_commands-BLDaEdQ6.js.map +0 -0
  88. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/pyscript/codemirror_lang-python-CkOVBHci.js +0 -0
  89. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/pyscript/codemirror_lang-python-CkOVBHci.js.map +0 -0
  90. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/pyscript/codemirror_language-DOkvasqm.js +0 -0
  91. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/pyscript/codemirror_language-DOkvasqm.js.map +0 -0
  92. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/pyscript/codemirror_state-BIAL8JKm.js +0 -0
  93. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/pyscript/codemirror_state-BIAL8JKm.js.map +0 -0
  94. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/pyscript/codemirror_view-Bt4sLgyA.js +0 -0
  95. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/pyscript/codemirror_view-Bt4sLgyA.js.map +0 -0
  96. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/pyscript/core-PTfg6inS.js +0 -0
  97. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/pyscript/core-PTfg6inS.js.map +0 -0
  98. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/pyscript/core.css +0 -0
  99. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/pyscript/core.js +0 -0
  100. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/pyscript/core.js.map +0 -0
  101. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/pyscript/deprecations-manager-DIDxhyRq.js +0 -0
  102. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/pyscript/deprecations-manager-DIDxhyRq.js.map +0 -0
  103. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/pyscript/donkey-CLhmQOjG.js +0 -0
  104. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/pyscript/donkey-CLhmQOjG.js.map +0 -0
  105. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/pyscript/error-uzvvriog.js +0 -0
  106. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/pyscript/error-uzvvriog.js.map +0 -0
  107. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/pyscript/index-jZ1aOVVJ.js +0 -0
  108. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/pyscript/index-jZ1aOVVJ.js.map +0 -0
  109. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/pyscript/mpy-CnF17tqI.js +0 -0
  110. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/pyscript/mpy-CnF17tqI.js.map +0 -0
  111. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/pyscript/py-BZSSqcx3.js +0 -0
  112. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/pyscript/py-BZSSqcx3.js.map +0 -0
  113. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/pyscript/py-editor-DZ0Dxzzk.js +0 -0
  114. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/pyscript/py-editor-DZ0Dxzzk.js.map +0 -0
  115. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/pyscript/py-game-bqieV522.js +0 -0
  116. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/pyscript/py-game-bqieV522.js.map +0 -0
  117. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/pyscript/py-terminal-DYY4WN57.js +0 -0
  118. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/pyscript/py-terminal-DYY4WN57.js.map +0 -0
  119. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/pyscript/service-worker.js +0 -0
  120. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/pyscript/storage.js +0 -0
  121. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/pyscript/storage.js.map +0 -0
  122. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/pyscript/toml-BK2RWy-G.js +0 -0
  123. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/pyscript/toml-BK2RWy-G.js.map +0 -0
  124. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/pyscript/toml-Blg7Izee.js +0 -0
  125. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/pyscript/toml-Blg7Izee.js.map +0 -0
  126. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/pyscript/xterm-DrSYbXEP.js +0 -0
  127. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/pyscript/xterm-DrSYbXEP.js.map +0 -0
  128. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/pyscript/xterm-readline-CK_45Ygx.js +0 -0
  129. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/pyscript/xterm-readline-CK_45Ygx.js.map +0 -0
  130. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/pyscript/xterm.css +0 -0
  131. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/pyscript/xterm_addon-fit--gyF3PcZ.js +0 -0
  132. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/pyscript/xterm_addon-fit--gyF3PcZ.js.map +0 -0
  133. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/pyscript/xterm_addon-web-links-D95xh2la.js +0 -0
  134. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/pyscript/xterm_addon-web-links-D95xh2la.js.map +0 -0
  135. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/pyscript/zip-pccs084i.js +0 -0
  136. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/pyscript/zip-pccs084i.js.map +0 -0
  137. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/static/pyscript-hide-debug.css +0 -0
  138. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/templatetags/__init__.py +0 -0
  139. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/templatetags/jinja.py +0 -0
  140. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/testing/__init__.py +0 -0
  141. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/testing/common.py +0 -0
  142. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/testing/utils.py +0 -0
  143. {reactpy-2.0.0b5 → reactpy-2.0.0b6}/src/reactpy/widgets.py +0 -0
@@ -1,5 +1,5 @@
1
1
  # --- Build Artifacts ---
2
- src/reactpy/static/index.js*
2
+ src/reactpy/static/*.js*
3
3
  src/reactpy/static/morphdom/
4
4
  src/reactpy/static/pyscript/
5
5
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: reactpy
3
- Version: 2.0.0b5
3
+ Version: 2.0.0b6
4
4
  Summary: It's React, but in Python.
5
5
  Project-URL: Changelog, https://reactpy.dev/docs/about/changelog.html
6
6
  Project-URL: Documentation, https://reactpy.dev/
@@ -39,12 +39,7 @@ classifiers = [
39
39
  "Programming Language :: Python :: Implementation :: CPython",
40
40
  "Programming Language :: Python :: Implementation :: PyPy",
41
41
  ]
42
- dependencies = [
43
- "fastjsonschema >=2.14.5",
44
- "requests >=2",
45
- "lxml >=4",
46
- "anyio >=3",
47
- ]
42
+ dependencies = ["fastjsonschema>=2.14.5", "requests>=2", "lxml>=4", "anyio>=3"]
48
43
  dynamic = ["version"]
49
44
  urls.Changelog = "https://reactpy.dev/docs/about/changelog.html"
50
45
  urls.Documentation = "https://reactpy.dev/"
@@ -53,7 +48,7 @@ urls.Source = "https://github.com/reactive-python/reactpy"
53
48
  [project.optional-dependencies]
54
49
  all = ["reactpy[asgi,jinja,testing]"]
55
50
  asgi = ["asgiref", "asgi-tools", "servestatic", "orjson"]
56
- jinja = ["jinja2-simple-tags", "jinja2 >=3"]
51
+ jinja = ["jinja2-simple-tags", "jinja2>=3"]
57
52
  testing = ["playwright", "uvicorn[standard]"]
58
53
 
59
54
  [tool.hatch.version]
@@ -13,29 +13,30 @@ import shutil
13
13
 
14
14
  # Get the path to the JS source directory
15
15
  js_src_dir = pathlib.Path(__file__).parent.parent / "js"
16
-
17
- # Get the paths to all `dist` folders in the JS source directory
18
- dist_dirs = glob.glob(str(js_src_dir / "**/dist"), recursive=True)
19
-
20
- # Get the paths to all `node_modules` folders in the JS source directory
21
- node_modules_dirs = glob.glob(str(js_src_dir / "**/node_modules"), recursive=True)
22
-
23
- # Get the paths to all `tsconfig.tsbuildinfo` files in the JS source directory
24
- tsconfig_tsbuildinfo_files = glob.glob(
25
- str(js_src_dir / "**/tsconfig.tsbuildinfo"), recursive=True
26
- )
16
+ static_output_dir = pathlib.Path(__file__).parent.parent / "reactpy" / "static"
27
17
 
28
18
  # Delete all `dist` folders
19
+ dist_dirs = glob.glob(str(js_src_dir / "**/dist"), recursive=True)
29
20
  for dist_dir in dist_dirs:
30
21
  with contextlib.suppress(FileNotFoundError):
31
22
  shutil.rmtree(dist_dir)
32
23
 
33
24
  # Delete all `node_modules` folders
25
+ node_modules_dirs = glob.glob(str(js_src_dir / "**/node_modules"), recursive=True)
34
26
  for node_modules_dir in node_modules_dirs:
35
27
  with contextlib.suppress(FileNotFoundError):
36
28
  shutil.rmtree(node_modules_dir)
37
29
 
38
30
  # Delete all `tsconfig.tsbuildinfo` files
31
+ tsconfig_tsbuildinfo_files = glob.glob(
32
+ str(js_src_dir / "**/tsconfig.tsbuildinfo"), recursive=True
33
+ )
39
34
  for tsconfig_tsbuildinfo_file in tsconfig_tsbuildinfo_files:
40
35
  with contextlib.suppress(FileNotFoundError):
41
36
  os.remove(tsconfig_tsbuildinfo_file)
37
+
38
+ # Delete all `index-*.js` files
39
+ index_js_files = glob.glob(str(static_output_dir / "index-*.js*"))
40
+ for index_js_file in index_js_files:
41
+ with contextlib.suppress(FileNotFoundError):
42
+ os.remove(index_js_file)
@@ -1,4 +1,4 @@
1
- from reactpy import config, logging, types, web, widgets
1
+ from reactpy import config, logging, reactjs, types, web, widgets
2
2
  from reactpy._html import html
3
3
  from reactpy.core import hooks
4
4
  from reactpy.core.component import component
@@ -23,7 +23,7 @@ from reactpy.pyscript.components import pyscript_component
23
23
  from reactpy.utils import Ref, reactpy_to_string, string_to_reactpy
24
24
 
25
25
  __author__ = "The Reactive Python Team"
26
- __version__ = "2.0.0b5"
26
+ __version__ = "2.0.0b6"
27
27
 
28
28
  __all__ = [
29
29
  "Ref",
@@ -36,6 +36,7 @@ __all__ = [
36
36
  "html",
37
37
  "logging",
38
38
  "pyscript_component",
39
+ "reactjs",
39
40
  "reactpy_to_string",
40
41
  "string_to_reactpy",
41
42
  "types",
@@ -6,7 +6,6 @@ from typing import ClassVar, overload
6
6
  from reactpy.core.vdom import Vdom
7
7
  from reactpy.types import (
8
8
  EventHandlerDict,
9
- Key,
10
9
  VdomAttributes,
11
10
  VdomChild,
12
11
  VdomChildren,
@@ -14,7 +13,7 @@ from reactpy.types import (
14
13
  VdomDict,
15
14
  )
16
15
 
17
- __all__ = ["html"]
16
+ __all__ = ["h", "html"]
18
17
 
19
18
  NO_CHILDREN_ALLOWED_HTML_BODY = {
20
19
  "area",
@@ -100,12 +99,10 @@ NO_CHILDREN_ALLOWED_SVG = {
100
99
  def _fragment(
101
100
  attributes: VdomAttributes,
102
101
  children: Sequence[VdomChild],
103
- key: Key | None,
104
102
  event_handlers: EventHandlerDict,
105
103
  ) -> VdomDict:
106
104
  """An HTML fragment - this element will not appear in the DOM"""
107
- attributes.pop("key", None)
108
- if attributes or event_handlers:
105
+ if any(k != "key" for k in attributes) or event_handlers:
109
106
  msg = "Fragments cannot have attributes besides 'key'"
110
107
  raise TypeError(msg)
111
108
  model = VdomDict(tagName="")
@@ -113,8 +110,8 @@ def _fragment(
113
110
  if children:
114
111
  model["children"] = children
115
112
 
116
- if key is not None:
117
- model["key"] = key
113
+ if attributes:
114
+ model["attributes"] = attributes
118
115
 
119
116
  return model
120
117
 
@@ -122,7 +119,6 @@ def _fragment(
122
119
  def _script(
123
120
  attributes: VdomAttributes,
124
121
  children: Sequence[VdomChild],
125
- key: Key | None,
126
122
  event_handlers: EventHandlerDict,
127
123
  ) -> VdomDict:
128
124
  """Create a new `<script> <https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script>`__ element.
@@ -148,6 +144,8 @@ def _script(
148
144
  msg = "'script' elements do not support event handlers"
149
145
  raise ValueError(msg)
150
146
 
147
+ key = attributes.get("key")
148
+
151
149
  if children:
152
150
  if len(children) > 1:
153
151
  msg = "'script' nodes may have, at most, one child."
@@ -165,7 +163,9 @@ def _script(
165
163
  key = attributes["src"]
166
164
 
167
165
  if key is not None:
168
- model["key"] = key
166
+ if "attributes" not in model:
167
+ model["attributes"] = {}
168
+ model["attributes"]["key"] = key
169
169
 
170
170
  return model
171
171
 
@@ -287,6 +287,7 @@ class HtmlConstructor:
287
287
  "fragment": Vdom("", custom_constructor=_fragment),
288
288
  "svg": SvgConstructor(),
289
289
  }
290
+ __call__ = __cache__["fragment"].__call__
290
291
 
291
292
  def __getattr__(self, value: str) -> VdomConstructor:
292
293
  value = value.rstrip("_").replace("_", "-")
@@ -423,3 +424,4 @@ class HtmlConstructor:
423
424
 
424
425
 
425
426
  html = HtmlConstructor()
427
+ h = html # shorthand alias for html
@@ -33,7 +33,10 @@ class _HookStack(Singleton): # nocov
33
33
  )
34
34
 
35
35
  def get(self) -> list[LifeCycleHook]:
36
- return self._state.get()
36
+ try:
37
+ return self._state.get()
38
+ except LookupError:
39
+ return []
37
40
 
38
41
  def initialize(self) -> Token[list[LifeCycleHook]] | None:
39
42
  return None if isinstance(self._state, ThreadLocal) else self._state.set([])
@@ -34,7 +34,7 @@ from reactpy.config import (
34
34
  REACTPY_CHECK_VDOM_SPEC,
35
35
  REACTPY_DEBUG,
36
36
  )
37
- from reactpy.core._life_cycle_hook import LifeCycleHook
37
+ from reactpy.core._life_cycle_hook import HOOK_STACK, LifeCycleHook
38
38
  from reactpy.core.vdom import validate_vdom_json
39
39
  from reactpy.types import (
40
40
  BaseLayout,
@@ -162,43 +162,47 @@ class Layout(BaseLayout):
162
162
  async def _create_layout_update(
163
163
  self, old_state: _ModelState
164
164
  ) -> LayoutUpdateMessage:
165
- component = old_state.life_cycle_state.component
165
+ token = HOOK_STACK.initialize()
166
166
  try:
167
- parent: _ModelState | None = old_state.parent
168
- except AttributeError:
169
- parent = None
170
-
171
- async with AsyncExitStack() as exit_stack:
172
- new_state = await self._render_component(
173
- exit_stack,
174
- old_state,
175
- parent,
176
- old_state.index,
177
- old_state.key,
178
- component,
179
- )
167
+ component = old_state.life_cycle_state.component
168
+ try:
169
+ parent: _ModelState | None = old_state.parent
170
+ except AttributeError:
171
+ parent = None
172
+
173
+ async with AsyncExitStack() as exit_stack:
174
+ new_state = await self._render_component(
175
+ exit_stack,
176
+ old_state,
177
+ parent,
178
+ old_state.index,
179
+ old_state.key,
180
+ component,
181
+ )
180
182
 
181
- if parent is not None:
182
- parent.children_by_key[new_state.key] = new_state
183
- old_parent_model = parent.model.current
184
- old_parent_children = old_parent_model.setdefault("children", [])
185
- parent.model.current = {
186
- **old_parent_model,
187
- "children": [
188
- *old_parent_children[: new_state.index],
189
- new_state.model.current,
190
- *old_parent_children[new_state.index + 1 :],
191
- ],
183
+ if parent is not None:
184
+ parent.children_by_key[new_state.key] = new_state
185
+ old_parent_model = parent.model.current
186
+ old_parent_children = old_parent_model.setdefault("children", [])
187
+ parent.model.current = {
188
+ **old_parent_model,
189
+ "children": [
190
+ *old_parent_children[: new_state.index],
191
+ new_state.model.current,
192
+ *old_parent_children[new_state.index + 1 :],
193
+ ],
194
+ }
195
+
196
+ if REACTPY_CHECK_VDOM_SPEC.current:
197
+ validate_vdom_json(new_state.model.current)
198
+
199
+ return {
200
+ "type": "layout-update",
201
+ "path": new_state.patch_path,
202
+ "model": new_state.model.current,
192
203
  }
193
-
194
- if REACTPY_CHECK_VDOM_SPEC.current:
195
- validate_vdom_json(new_state.model.current)
196
-
197
- return {
198
- "type": "layout-update",
199
- "path": new_state.patch_path,
200
- "model": new_state.model.current,
201
- }
204
+ finally:
205
+ HOOK_STACK.reset(token)
202
206
 
203
207
  async def _render_component(
204
208
  self,
@@ -299,8 +303,9 @@ class Layout(BaseLayout):
299
303
  except Exception as e: # nocov
300
304
  msg = f"Expected a VDOM element dict, not {raw_model}"
301
305
  raise ValueError(msg) from e
302
- if "key" in raw_model:
303
- new_state.key = new_state.model.current["key"] = raw_model["key"]
306
+ key = raw_model.get("attributes", {}).get("key")
307
+ if key is not None:
308
+ new_state.key = key
304
309
  if "importSource" in raw_model:
305
310
  new_state.model.current["importSource"] = raw_model["importSource"]
306
311
  self._render_model_attributes(old_state, new_state, raw_model)
@@ -722,7 +727,7 @@ def _get_children_info(
722
727
  continue
723
728
  elif isinstance(child, dict):
724
729
  child_type = _DICT_TYPE
725
- key = child.get("key")
730
+ key = child.get("attributes", {}).get("key")
726
731
  elif isinstance(child, Component):
727
732
  child_type = _COMPONENT_TYPE
728
733
  key = child.key
@@ -8,7 +8,6 @@ from anyio import create_task_group
8
8
  from anyio.abc import TaskGroup
9
9
 
10
10
  from reactpy.config import REACTPY_DEBUG
11
- from reactpy.core._life_cycle_hook import HOOK_STACK
12
11
  from reactpy.types import BaseLayout, LayoutEventMessage, LayoutUpdateMessage
13
12
 
14
13
  logger = getLogger(__name__)
@@ -45,22 +44,18 @@ async def _single_outgoing_loop(
45
44
  send: SendCoroutine,
46
45
  ) -> None:
47
46
  while True:
48
- token = HOOK_STACK.initialize()
47
+ update = await layout.render()
49
48
  try:
50
- update = await layout.render()
51
- try:
52
- await send(update)
53
- except Exception: # nocov
54
- if not REACTPY_DEBUG.current:
55
- msg = (
56
- "Failed to send update. More info may be available "
57
- "if you enabling debug mode by setting "
58
- "`reactpy.config.REACTPY_DEBUG.current = True`."
59
- )
60
- logger.error(msg)
61
- raise
62
- finally:
63
- HOOK_STACK.reset(token)
49
+ await send(update)
50
+ except Exception: # nocov
51
+ if not REACTPY_DEBUG.current:
52
+ msg = (
53
+ "Failed to send update. More info may be available "
54
+ "if you enabling debug mode by setting "
55
+ "`reactpy.config.REACTPY_DEBUG.current = True`."
56
+ )
57
+ logger.error(msg)
58
+ raise
64
59
 
65
60
 
66
61
  async def _single_incoming_loop(
@@ -41,7 +41,6 @@ VDOM_JSON_SCHEMA = {
41
41
  "type": "object",
42
42
  "properties": {
43
43
  "tagName": {"type": "string"},
44
- "key": {"type": ["string", "number", "null"]},
45
44
  "error": {"type": "string"},
46
45
  "children": {"$ref": "#/definitions/elementChildren"},
47
46
  "attributes": {"type": "object"},
@@ -170,7 +169,6 @@ class Vdom:
170
169
  ) -> VdomDict:
171
170
  """The entry point for the VDOM API, for example reactpy.html(<WE_ARE_HERE>)."""
172
171
  attributes, children = separate_attributes_and_children(attributes_and_children)
173
- key = attributes.get("key", None)
174
172
  attributes, event_handlers, inline_javascript = (
175
173
  separate_attributes_handlers_and_inline_javascript(attributes)
176
174
  )
@@ -180,7 +178,6 @@ class Vdom:
180
178
  # Run custom constructor, if defined
181
179
  if self.custom_constructor:
182
180
  result = self.custom_constructor(
183
- key=key,
184
181
  children=children,
185
182
  attributes=attributes,
186
183
  event_handlers=event_handlers,
@@ -189,7 +186,6 @@ class Vdom:
189
186
  # Otherwise, use the default constructor
190
187
  else:
191
188
  result = {
192
- **({"key": key} if key is not None else {}),
193
189
  **({"children": children} if children else {}),
194
190
  **({"attributes": attributes} if attributes else {}),
195
191
  **({"eventHandlers": event_handlers} if event_handlers else {}),
@@ -277,7 +273,9 @@ def _validate_child_key_integrity(value: Any) -> None:
277
273
  for child in value:
278
274
  if isinstance(child, Component) and child.key is None:
279
275
  warn(f"Key not specified for child in list {child}", UserWarning)
280
- elif isinstance(child, Mapping) and "key" not in child:
276
+ elif isinstance(child, Mapping) and "key" not in child.get(
277
+ "attributes", {}
278
+ ):
281
279
  # remove 'children' to reduce log spam
282
280
  child_copy = {**child, "children": EllipsisRepr()}
283
281
  warn(f"Key not specified for child in list {child_copy}", UserWarning)
@@ -123,7 +123,7 @@ def extend_pyscript_config(
123
123
  pyscript_config["packages"].extend(extra_py)
124
124
 
125
125
  # FIXME: https://github.com/pyscript/pyscript/issues/2282
126
- if any(pkg.endswith(".whl") for pkg in pyscript_config["packages"]):
126
+ if any(pkg.endswith(".whl") for pkg in pyscript_config["packages"]): # nocov
127
127
  pyscript_config["packages_cache"] = "never"
128
128
 
129
129
  # Extend the JavaScript dependency list