From 618e5792ef7f6288647efed3dcc7dda61df8d957 Mon Sep 17 00:00:00 2001 From: Mark Bakhit Date: Tue, 5 Mar 2024 18:50:00 -0800 Subject: [PATCH 01/16] Update PR template and VSCode workspace (#1053) --- .github/pull_request_template.md | 18 +++++++++--------- .vscode/extensions.json | 12 ++++++++++++ docs/source/about/changelog.rst | 13 ++++--------- 3 files changed, 25 insertions(+), 18 deletions(-) create mode 100644 .vscode/extensions.json diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index d762951b3..a55532008 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,14 +1,14 @@ -By submitting this pull request you agree that all contributions to this project are made under the MIT license. +## Description -## Issues + - - -## Solution +## Checklist - +Please update this checklist as you complete each item: -## Checklist +- [ ] Tests have been developed for bug fixes or new functionality. +- [ ] The changelog has been updated, if necessary. +- [ ] Documentation has been updated, if necessary. +- [ ] GitHub Issues closed by this PR have been linked. -- [ ] Tests have been included for all bug fixes or added functionality. -- [ ] The `changelog.rst` has been updated with any significant changes. +By submitting this pull request I agree that all contributions comply with this project's open source license(s). diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 000000000..7471953dc --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,12 @@ +{ + "recommendations": [ + "wholroyd.jinja", + "esbenp.prettier-vscode", + "ms-python.vscode-pylance", + "ms-python.python", + "charliermarsh.ruff", + "dbaeumer.vscode-eslint", + "ms-python.black-formatter", + "ms-python.mypy-type-checker" + ] +} diff --git a/docs/source/about/changelog.rst b/docs/source/about/changelog.rst index feecbd1f0..bc8e164b4 100644 --- a/docs/source/about/changelog.rst +++ b/docs/source/about/changelog.rst @@ -3,15 +3,10 @@ Changelog .. note:: - The ReactPy team manages their short and long term plans with `GitHub Projects - `__. If you have questions about what - the team are working on, or have feedback on how issues should be prioritized, feel - free to :discussion-type:`open up a discussion `. - -All notable changes to this project will be recorded in this document. The style of -which is based on `Keep a Changelog `__. The versioning -scheme for the project adheres to `Semantic Versioning `__. For -more info, see the :ref:`Contributor Guide `. + All notable changes to this project will be recorded in this document. The style of + which is based on `Keep a Changelog `__. The versioning + scheme for the project adheres to `Semantic Versioning `__. For + more info, see the :ref:`Contributor Guide `. .. INSTRUCTIONS FOR CHANGELOG CONTRIBUTORS From 3f05f81e53f28afa06c6c3f3c80c3ef0b9fe1aa6 Mon Sep 17 00:00:00 2001 From: Mark Bakhit Date: Tue, 5 Mar 2024 19:13:39 -0800 Subject: [PATCH 02/16] Use `utf-8` for reading files (#1200) --- docs/source/about/changelog.rst | 1 + src/py/reactpy/reactpy/_console/rewrite_camel_case_props.py | 2 +- src/py/reactpy/reactpy/_console/rewrite_keys.py | 2 +- src/py/reactpy/reactpy/web/module.py | 4 ++-- src/py/reactpy/reactpy/web/utils.py | 2 +- 5 files changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/source/about/changelog.rst b/docs/source/about/changelog.rst index bc8e164b4..b2297c20c 100644 --- a/docs/source/about/changelog.rst +++ b/docs/source/about/changelog.rst @@ -22,6 +22,7 @@ Unreleased - :pull:`1118` - `module_from_template` is broken with a recent release of `requests` - :pull:`1131` - `module_from_template` did not work when using Flask backend +- :pull:`1200` - Fixed `UnicodeDecodeError` when using `reactpy.web.export` **Added** diff --git a/src/py/reactpy/reactpy/_console/rewrite_camel_case_props.py b/src/py/reactpy/reactpy/_console/rewrite_camel_case_props.py index e5d1860c2..d706adecf 100644 --- a/src/py/reactpy/reactpy/_console/rewrite_camel_case_props.py +++ b/src/py/reactpy/reactpy/_console/rewrite_camel_case_props.py @@ -29,7 +29,7 @@ def rewrite_camel_case_props(paths: list[str]) -> None: for p in map(Path, paths): for f in [p] if p.is_file() else p.rglob("*.py"): - result = generate_rewrite(file=f, source=f.read_text()) + result = generate_rewrite(file=f, source=f.read_text(encoding="utf-8")) if result is not None: f.write_text(result) diff --git a/src/py/reactpy/reactpy/_console/rewrite_keys.py b/src/py/reactpy/reactpy/_console/rewrite_keys.py index 64ed42f33..08db9e227 100644 --- a/src/py/reactpy/reactpy/_console/rewrite_keys.py +++ b/src/py/reactpy/reactpy/_console/rewrite_keys.py @@ -51,7 +51,7 @@ def rewrite_keys(paths: list[str]) -> None: for p in map(Path, paths): for f in [p] if p.is_file() else p.rglob("*.py"): - result = generate_rewrite(file=f, source=f.read_text()) + result = generate_rewrite(file=f, source=f.read_text(encoding="utf-8")) if result is not None: f.write_text(result) diff --git a/src/py/reactpy/reactpy/web/module.py b/src/py/reactpy/reactpy/web/module.py index c3192da4e..e1a5db82f 100644 --- a/src/py/reactpy/reactpy/web/module.py +++ b/src/py/reactpy/reactpy/web/module.py @@ -145,7 +145,7 @@ def module_from_template( raise ValueError(msg) variables = {"PACKAGE": package, "CDN": cdn, "VERSION": template_version} - content = Template(template_file.read_text()).substitute(variables) + content = Template(template_file.read_text(encoding="utf-8")).substitute(variables) return module_from_string( _FROM_TEMPLATE_DIR + "/" + package_name, @@ -270,7 +270,7 @@ def module_from_string( target_file = _web_module_path(name) - if target_file.exists() and target_file.read_text() != content: + if target_file.exists() and target_file.read_text(encoding="utf-8") != content: logger.info( f"Existing web module {name!r} will " f"be replaced with {target_file.resolve()}" diff --git a/src/py/reactpy/reactpy/web/utils.py b/src/py/reactpy/reactpy/web/utils.py index 295559496..338fa504a 100644 --- a/src/py/reactpy/reactpy/web/utils.py +++ b/src/py/reactpy/reactpy/web/utils.py @@ -29,7 +29,7 @@ def resolve_module_exports_from_file( return set() export_names, references = resolve_module_exports_from_source( - file.read_text(), exclude_default=is_re_export + file.read_text(encoding="utf-8"), exclude_default=is_re_export ) for ref in references: From 2c6a1f78674399f12d3071924969f6e56cecfc0c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Mar 2024 19:27:03 -0800 Subject: [PATCH 03/16] Bump postcss from 8.4.24 to 8.4.35 in /src/js (#1205) Bumps [postcss](https://github.com/postcss/postcss) from 8.4.24 to 8.4.35. - [Release notes](https://github.com/postcss/postcss/releases) - [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md) - [Commits](https://github.com/postcss/postcss/compare/8.4.24...8.4.35) --- updated-dependencies: - dependency-name: postcss dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/js/package-lock.json | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/js/package-lock.json b/src/js/package-lock.json index 2edfdd260..d836d2798 100644 --- a/src/js/package-lock.json +++ b/src/js/package-lock.json @@ -28,7 +28,7 @@ "@types/react": "^17.0", "@types/react-dom": "^17.0", "typescript": "^4.9.5", - "vite": "^3.1.8" + "vite": "^3.2.7" } }, "app/node_modules/@reactpy/client": { @@ -2429,9 +2429,9 @@ "dev": true }, "node_modules/nanoid": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", "dev": true, "funding": [ { @@ -2712,9 +2712,9 @@ } }, "node_modules/postcss": { - "version": "8.4.24", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.24.tgz", - "integrity": "sha512-M0RzbcI0sO/XJNucsGjvWU9ERWxb/ytp1w6dKtxTKgixdtQDq4rmx/g8W1hnaheq9jgwL/oyEdH5Bc4WwJKMqg==", + "version": "8.4.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz", + "integrity": "sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==", "dev": true, "funding": [ { @@ -2731,7 +2731,7 @@ } ], "dependencies": { - "nanoid": "^3.3.6", + "nanoid": "^3.3.7", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" }, @@ -3955,7 +3955,7 @@ "@types/react-dom": "^17.0", "preact": "^10.7.0", "typescript": "^4.9.5", - "vite": "^3.1.8" + "vite": "^3.2.7" }, "dependencies": { "@reactpy/client": { @@ -5285,9 +5285,9 @@ "dev": true }, "nanoid": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", "dev": true }, "natural-compare": { @@ -5476,12 +5476,12 @@ "dev": true }, "postcss": { - "version": "8.4.24", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.24.tgz", - "integrity": "sha512-M0RzbcI0sO/XJNucsGjvWU9ERWxb/ytp1w6dKtxTKgixdtQDq4rmx/g8W1hnaheq9jgwL/oyEdH5Bc4WwJKMqg==", + "version": "8.4.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz", + "integrity": "sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==", "dev": true, "requires": { - "nanoid": "^3.3.6", + "nanoid": "^3.3.7", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } From 34a2d24dab0501f553c43a8d6c9737d58599f899 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 6 Mar 2024 03:41:15 +0000 Subject: [PATCH 04/16] Bump postcss from 8.4.21 to 8.4.35 in /src/js/app (#1208) --- src/js/app/package-lock.json | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/src/js/app/package-lock.json b/src/js/app/package-lock.json index 9794c53d6..1a254ec74 100644 --- a/src/js/app/package-lock.json +++ b/src/js/app/package-lock.json @@ -540,9 +540,9 @@ } }, "node_modules/nanoid": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", "dev": true, "funding": [ { @@ -579,9 +579,9 @@ "dev": true }, "node_modules/postcss": { - "version": "8.4.21", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz", - "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==", + "version": "8.4.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz", + "integrity": "sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==", "dev": true, "funding": [ { @@ -591,10 +591,14 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ], "dependencies": { - "nanoid": "^3.3.4", + "nanoid": "^3.3.7", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" }, @@ -1064,9 +1068,9 @@ } }, "nanoid": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", "dev": true }, "object-assign": { @@ -1088,12 +1092,12 @@ "dev": true }, "postcss": { - "version": "8.4.21", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz", - "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==", + "version": "8.4.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz", + "integrity": "sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==", "dev": true, "requires": { - "nanoid": "^3.3.4", + "nanoid": "^3.3.7", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } From 97c3b19a6ebeacd9b3b0d58cfbd294fc1b66a119 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Mar 2024 23:01:03 -0800 Subject: [PATCH 05/16] Bump vite from 3.2.7 to 3.2.8 in /src/js (#1207) Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 3.2.7 to 3.2.8. - [Release notes](https://github.com/vitejs/vite/releases) - [Changelog](https://github.com/vitejs/vite/blob/v3.2.8/packages/vite/CHANGELOG.md) - [Commits](https://github.com/vitejs/vite/commits/v3.2.8/packages/vite) --- updated-dependencies: - dependency-name: vite dependency-type: direct:development ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Mark Bakhit --- src/js/app/package.json | 2 +- src/js/package-lock.json | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/js/app/package.json b/src/js/app/package.json index 40ce94739..55a42fd66 100644 --- a/src/js/app/package.json +++ b/src/js/app/package.json @@ -12,7 +12,7 @@ "@types/react": "^17.0", "@types/react-dom": "^17.0", "typescript": "^4.9.5", - "vite": "^3.2.7" + "vite": "^3.2.8" }, "repository": { "type": "git", diff --git a/src/js/package-lock.json b/src/js/package-lock.json index d836d2798..9e5f9678e 100644 --- a/src/js/package-lock.json +++ b/src/js/package-lock.json @@ -28,7 +28,7 @@ "@types/react": "^17.0", "@types/react-dom": "^17.0", "typescript": "^4.9.5", - "vite": "^3.2.7" + "vite": "^3.2.8" } }, "app/node_modules/@reactpy/client": { @@ -3328,9 +3328,9 @@ } }, "node_modules/vite": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/vite/-/vite-3.2.7.tgz", - "integrity": "sha512-29pdXjk49xAP0QBr0xXqu2s5jiQIXNvE/xwd0vUizYT2Hzqe4BksNNoWllFVXJf4eLZ+UlVQmXfB4lWrc+t18g==", + "version": "3.2.8", + "resolved": "https://registry.npmjs.org/vite/-/vite-3.2.8.tgz", + "integrity": "sha512-EtQU16PLIJpAZol2cTLttNP1mX6L0SyI0pgQB1VOoWeQnMSvtiwovV3D6NcjN8CZQWWyESD2v5NGnpz5RvgOZA==", "dev": true, "dependencies": { "esbuild": "^0.15.9", @@ -3955,7 +3955,7 @@ "@types/react-dom": "^17.0", "preact": "^10.7.0", "typescript": "^4.9.5", - "vite": "^3.2.7" + "vite": "^3.2.8" }, "dependencies": { "@reactpy/client": { @@ -5888,9 +5888,9 @@ } }, "vite": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/vite/-/vite-3.2.7.tgz", - "integrity": "sha512-29pdXjk49xAP0QBr0xXqu2s5jiQIXNvE/xwd0vUizYT2Hzqe4BksNNoWllFVXJf4eLZ+UlVQmXfB4lWrc+t18g==", + "version": "3.2.8", + "resolved": "https://registry.npmjs.org/vite/-/vite-3.2.8.tgz", + "integrity": "sha512-EtQU16PLIJpAZol2cTLttNP1mX6L0SyI0pgQB1VOoWeQnMSvtiwovV3D6NcjN8CZQWWyESD2v5NGnpz5RvgOZA==", "dev": true, "requires": { "esbuild": "^0.15.9", From 044eb17c7200b31086e4357a4cf04c133cd5f37c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Mar 2024 23:11:10 -0800 Subject: [PATCH 06/16] Bump vite from 3.2.7 to 3.2.8 in /src/js/app (#1206) Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 3.2.7 to 3.2.8. - [Release notes](https://github.com/vitejs/vite/releases) - [Changelog](https://github.com/vitejs/vite/blob/v3.2.8/packages/vite/CHANGELOG.md) - [Commits](https://github.com/vitejs/vite/commits/v3.2.8/packages/vite) --- updated-dependencies: - dependency-name: vite dependency-type: direct:development ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Mark Bakhit --- src/js/app/package-lock.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/js/app/package-lock.json b/src/js/app/package-lock.json index 1a254ec74..adc398279 100644 --- a/src/js/app/package-lock.json +++ b/src/js/app/package-lock.json @@ -13,7 +13,7 @@ "@types/react": "^17.0", "@types/react-dom": "^17.0", "typescript": "^4.9.5", - "vite": "^3.2.7" + "vite": "^3.2.8" } }, "node_modules/@esbuild/android-arm": { @@ -719,9 +719,9 @@ } }, "node_modules/vite": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/vite/-/vite-3.2.7.tgz", - "integrity": "sha512-29pdXjk49xAP0QBr0xXqu2s5jiQIXNvE/xwd0vUizYT2Hzqe4BksNNoWllFVXJf4eLZ+UlVQmXfB4lWrc+t18g==", + "version": "3.2.8", + "resolved": "https://registry.npmjs.org/vite/-/vite-3.2.8.tgz", + "integrity": "sha512-EtQU16PLIJpAZol2cTLttNP1mX6L0SyI0pgQB1VOoWeQnMSvtiwovV3D6NcjN8CZQWWyESD2v5NGnpz5RvgOZA==", "dev": true, "dependencies": { "esbuild": "^0.15.9", @@ -1177,9 +1177,9 @@ "dev": true }, "vite": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/vite/-/vite-3.2.7.tgz", - "integrity": "sha512-29pdXjk49xAP0QBr0xXqu2s5jiQIXNvE/xwd0vUizYT2Hzqe4BksNNoWllFVXJf4eLZ+UlVQmXfB4lWrc+t18g==", + "version": "3.2.8", + "resolved": "https://registry.npmjs.org/vite/-/vite-3.2.8.tgz", + "integrity": "sha512-EtQU16PLIJpAZol2cTLttNP1mX6L0SyI0pgQB1VOoWeQnMSvtiwovV3D6NcjN8CZQWWyESD2v5NGnpz5RvgOZA==", "dev": true, "requires": { "esbuild": "^0.15.9", From 4307a09dfa75e6c1b10a285e5ae4bdf0323cd018 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 6 Mar 2024 07:21:50 +0000 Subject: [PATCH 07/16] Bump word-wrap from 1.2.3 to 1.2.5 in /src/js (#1209) --- src/js/package-lock.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/js/package-lock.json b/src/js/package-lock.json index 9e5f9678e..91b7f302c 100644 --- a/src/js/package-lock.json +++ b/src/js/package-lock.json @@ -3474,9 +3474,9 @@ } }, "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true, "engines": { "node": ">=0.10.0" @@ -5976,9 +5976,9 @@ } }, "word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true }, "wrappy": { From f6f13f0e0f483217111481e2c1d4e7697116f9a9 Mon Sep 17 00:00:00 2001 From: Mark Bakhit Date: Thu, 7 Mar 2024 19:26:20 -0800 Subject: [PATCH 08/16] Concurrent rendering naming fixes (#1211) --- docs/source/about/changelog.rst | 8 ++++---- src/py/reactpy/reactpy/config.py | 4 ++-- src/py/reactpy/reactpy/core/layout.py | 8 +++++--- src/py/reactpy/tests/test_core/test_layout.py | 8 ++++---- 4 files changed, 15 insertions(+), 13 deletions(-) diff --git a/docs/source/about/changelog.rst b/docs/source/about/changelog.rst index b2297c20c..9fc13e015 100644 --- a/docs/source/about/changelog.rst +++ b/docs/source/about/changelog.rst @@ -26,10 +26,10 @@ Unreleased **Added** -- :pull:`1165` - Allow concurrent renders of discrete component tree - enable this - experimental feature by setting `REACTPY_ASYNC_RENDERING=true`. This should improve - the overall responsiveness of your app, particularly when handling larger renders - that would otherwise block faster renders from being processed. +- :pull:`1165` - Allow concurrently rendering discrete component trees - enable this + experimental feature by setting `REACTPY_ASYNC_RENDERING=true`. This improves + the overall responsiveness of your app in situations where larger renders would + otherwise block smaller renders from executing. **Changed** diff --git a/src/py/reactpy/reactpy/config.py b/src/py/reactpy/reactpy/config.py index 8ea6aed03..d08cdc218 100644 --- a/src/py/reactpy/reactpy/config.py +++ b/src/py/reactpy/reactpy/config.py @@ -82,9 +82,9 @@ def boolean(value: str | bool | int) -> bool: """A default timeout for testing utilities in ReactPy""" REACTPY_ASYNC_RENDERING = Option( - "REACTPY_CONCURRENT_RENDERING", + "REACTPY_ASYNC_RENDERING", default=False, mutable=True, validator=boolean, ) -"""Whether to render components concurrently. This is currently an experimental feature.""" +"""Whether to render components asynchronously. This is currently an experimental feature.""" diff --git a/src/py/reactpy/reactpy/core/layout.py b/src/py/reactpy/reactpy/core/layout.py index 70bdbbbff..f45becf7a 100644 --- a/src/py/reactpy/reactpy/core/layout.py +++ b/src/py/reactpy/reactpy/core/layout.py @@ -129,7 +129,7 @@ async def deliver(self, event: LayoutEventMessage) -> None: async def render(self) -> LayoutUpdateMessage: if REACTPY_ASYNC_RENDERING.current: - return await self._concurrent_render() + return await self._parallel_render() else: # nocov return await self._serial_render() @@ -147,8 +147,10 @@ async def _serial_render(self) -> LayoutUpdateMessage: # nocov else: return await self._create_layout_update(model_state) - async def _concurrent_render(self) -> LayoutUpdateMessage: - """Await the next available render. This will block until a component is updated""" + async def _parallel_render(self) -> LayoutUpdateMessage: + """Await to fetch the first completed render within our asyncio task group. + We use the `asyncio.tasks.wait` API in order to return the first completed task. + """ await self._render_tasks_ready.acquire() done, _ = await wait(self._render_tasks, return_when=FIRST_COMPLETED) update_task: Task[LayoutUpdateMessage] = done.pop() diff --git a/src/py/reactpy/tests/test_core/test_layout.py b/src/py/reactpy/tests/test_core/test_layout.py index cfb544758..f93ffeb3d 100644 --- a/src/py/reactpy/tests/test_core/test_layout.py +++ b/src/py/reactpy/tests/test_core/test_layout.py @@ -32,7 +32,7 @@ @pytest.fixture(autouse=True, params=[True, False]) -def concurrent_rendering(request): +def async_rendering(request): with patch.object(REACTPY_ASYNC_RENDERING, "current", request.param): yield request.param @@ -1252,9 +1252,9 @@ def App(): assert c["attributes"]["color"] == "blue" -async def test_concurrent_renders(concurrent_rendering): - if not concurrent_rendering: - raise pytest.skip("Concurrent rendering not enabled") +async def test_async_renders(async_rendering): + if not async_rendering: + raise pytest.skip("Async rendering not enabled") child_1_hook = HookCatcher() child_2_hook = HookCatcher() From f81c1680106164cb1a9eb28f6955f1dbbcfd7063 Mon Sep 17 00:00:00 2001 From: Mark Bakhit Date: Mon, 28 Oct 2024 20:23:08 -0700 Subject: [PATCH 09/16] Fix the CI (#1233) --- .github/workflows/.hatch-run.yml | 2 +- pyproject.toml | 7 +-- src/py/reactpy/pyproject.toml | 56 +++++-------------- src/py/reactpy/reactpy/core/events.py | 2 +- src/py/reactpy/reactpy/core/layout.py | 2 +- src/py/reactpy/reactpy/utils.py | 2 +- src/py/reactpy/tests/test_backend/test_all.py | 5 ++ src/py/reactpy/tests/test_core/test_events.py | 2 +- 8 files changed, 26 insertions(+), 52 deletions(-) diff --git a/.github/workflows/.hatch-run.yml b/.github/workflows/.hatch-run.yml index 1b21e4202..d18e3a190 100644 --- a/.github/workflows/.hatch-run.yml +++ b/.github/workflows/.hatch-run.yml @@ -41,7 +41,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-node@v2 with: - node-version: "14.x" + node-version: "23.x" registry-url: ${{ inputs.node-registry-url }} - name: Pin NPM Version run: npm install -g npm@8.19.3 diff --git a/pyproject.toml b/pyproject.toml index 775ab01a2..1745a3dfe 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,12 +12,11 @@ detached = true dependencies = [ "invoke", # lint - "black==24.1.1", # Pin lint tools we don't control to avoid breaking changes - "ruff==0.0.278", # Pin lint tools we don't control to avoid breaking changes + "black==24.1.1", # Pin lint tools we don't control to avoid breaking changes + "ruff==0.0.278", # Pin lint tools we don't control to avoid breaking changes "toml", - "flake8==7.0.0", # Pin lint tools we don't control to avoid breaking changes + "flake8==7.0.0", # Pin lint tools we don't control to avoid breaking changes "flake8-pyproject", - "reactpy-flake8 >=0.7", # types "mypy", "types-toml", diff --git a/src/py/reactpy/pyproject.toml b/src/py/reactpy/pyproject.toml index 309248507..e5a2559b7 100644 --- a/src/py/reactpy/pyproject.toml +++ b/src/py/reactpy/pyproject.toml @@ -12,9 +12,7 @@ readme = "README.md" requires-python = ">=3.9" license = "MIT" keywords = ["react", "javascript", "reactpy", "component"] -authors = [ - { name = "Ryan Morshead", email = "ryan.morshead@gmail.com" }, -] +authors = [{ name = "Ryan Morshead", email = "ryan.morshead@gmail.com" }] classifiers = [ "Development Status :: 4 - Beta", "Programming Language :: Python", @@ -39,10 +37,7 @@ dependencies = [ [project.optional-dependencies] all = ["reactpy[starlette,sanic,fastapi,flask,tornado,testing]"] -starlette = [ - "starlette >=0.13.6", - "uvicorn[standard] >=0.19.0", -] +starlette = ["starlette >=0.13.6", "uvicorn[standard] >=0.19.0"] sanic = [ "sanic >=21", "sanic-cors", @@ -50,22 +45,10 @@ sanic = [ "setuptools", "uvicorn[standard] >=0.19.0", ] -fastapi = [ - "fastapi >=0.63.0", - "uvicorn[standard] >=0.19.0", -] -flask = [ - "flask", - "markupsafe>=1.1.1,<2.1", - "flask-cors", - "flask-sock", -] -tornado = [ - "tornado", -] -testing = [ - "playwright", -] +fastapi = ["fastapi >=0.63.0", "uvicorn[standard] >=0.19.0"] +flask = ["flask", "markupsafe>=1.1.1,<2.1", "flask-cors", "flask-sock"] +tornado = ["tornado"] +testing = ["playwright"] [project.urls] Source = "https://github.com/reactive-python/reactpy" @@ -101,21 +84,17 @@ cov-report = [ # "- coverage combine", "coverage report", ] -cov = [ - "test-cov {args}", - "cov-report", -] +cov = ["test-cov {args}", "cov-report"] [tool.hatch.envs.default.env-vars] -REACTPY_DEBUG_MODE="1" +REACTPY_DEBUG_MODE = "1" [tool.hatch.envs.lint] features = ["all"] dependencies = [ - "mypy>=1.0.0", + "mypy==1.8", "types-click", "types-tornado", - "types-pkg-resources", "types-flask", "types-requests", ] @@ -127,13 +106,8 @@ all = ["types"] [[tool.hatch.build.hooks.build-scripts.scripts]] work_dir = "../../js" out_dir = "reactpy/_static" -commands = [ - "npm ci", - "npm run build" -] -artifacts = [ - "app/dist/" -] +commands = ["npm ci", "npm run build"] +artifacts = ["app/dist/"] # --- Pytest --------------------------------------------------------------------------- @@ -159,9 +133,7 @@ warn_unused_ignores = true source_pkgs = ["reactpy"] branch = false parallel = false -omit = [ - "reactpy/__init__.py", -] +omit = ["reactpy/__init__.py"] [tool.coverage.report] fail_under = 100 @@ -174,6 +146,4 @@ exclude_lines = [ "if __name__ == .__main__.:", "if TYPE_CHECKING:", ] -omit = [ - "reactpy/__main__.py", -] +omit = ["reactpy/__main__.py"] diff --git a/src/py/reactpy/reactpy/core/events.py b/src/py/reactpy/reactpy/core/events.py index f715b7e9d..2a193ec6b 100644 --- a/src/py/reactpy/reactpy/core/events.py +++ b/src/py/reactpy/reactpy/core/events.py @@ -109,7 +109,7 @@ def __init__( self.stop_propagation = stop_propagation self.target = target - def __eq__(self, other: Any) -> bool: + def __eq__(self, other: object) -> bool: undefined = object() for attr in ( "function", diff --git a/src/py/reactpy/reactpy/core/layout.py b/src/py/reactpy/reactpy/core/layout.py index f45becf7a..88cb2fa35 100644 --- a/src/py/reactpy/reactpy/core/layout.py +++ b/src/py/reactpy/reactpy/core/layout.py @@ -89,7 +89,7 @@ async def __aenter__(self) -> Layout: return self - async def __aexit__(self, *exc: Any) -> None: + async def __aexit__(self, *exc: object) -> None: root_csid = self._root_life_cycle_state_id root_model_state = self._model_states_by_life_cycle_state_id[root_csid] diff --git a/src/py/reactpy/reactpy/utils.py b/src/py/reactpy/reactpy/utils.py index 5624846a4..a20194902 100644 --- a/src/py/reactpy/reactpy/utils.py +++ b/src/py/reactpy/reactpy/utils.py @@ -43,7 +43,7 @@ def set_current(self, new: _RefValue) -> _RefValue: self.current = new return old - def __eq__(self, other: Any) -> bool: + def __eq__(self, other: object) -> bool: try: return isinstance(other, Ref) and (other.current == self.current) except AttributeError: diff --git a/src/py/reactpy/tests/test_backend/test_all.py b/src/py/reactpy/tests/test_backend/test_all.py index dc8ec1284..9a1440d52 100644 --- a/src/py/reactpy/tests/test_backend/test_all.py +++ b/src/py/reactpy/tests/test_backend/test_all.py @@ -1,3 +1,4 @@ +import sys from collections.abc import MutableMapping import pytest @@ -106,6 +107,10 @@ def ShowScope(): assert isinstance(scope.current, MutableMapping) +@pytest.mark.skipIf( + sys.platform == "darwin", + reason="Tornado and Flask backends are currently buggy on MacOS.", +) async def test_use_location(display: DisplayFixture): location = reactpy.Ref() diff --git a/src/py/reactpy/tests/test_core/test_events.py b/src/py/reactpy/tests/test_core/test_events.py index 237c9d4ed..b6fea346a 100644 --- a/src/py/reactpy/tests/test_core/test_events.py +++ b/src/py/reactpy/tests/test_core/test_events.py @@ -193,7 +193,7 @@ def inner_click_no_op(event): clicked.current = True def outer_click_is_not_triggered(event): - raise AssertionError() + raise AssertionError outer = reactpy.html.div( { From 3dc0c231fc4e14bb34f02d0f2f31c953273d21e1 Mon Sep 17 00:00:00 2001 From: Mark Bakhit Date: Tue, 29 Oct 2024 03:24:04 -0700 Subject: [PATCH 10/16] Fix flakey `use_location` test (#1234) * Fix flakey `use_location` test * Bump workflow versions --- .github/workflows/.hatch-run.yml | 6 +-- .github/workflows/deploy-docs.yml | 44 +++++++++---------- .github/workflows/publish.yml | 24 +++++----- src/py/reactpy/tests/test_backend/test_all.py | 7 +-- 4 files changed, 38 insertions(+), 43 deletions(-) diff --git a/.github/workflows/.hatch-run.yml b/.github/workflows/.hatch-run.yml index d18e3a190..1630378b9 100644 --- a/.github/workflows/.hatch-run.yml +++ b/.github/workflows/.hatch-run.yml @@ -38,15 +38,15 @@ jobs: runs-on: ${{ fromJson(inputs.runs-on-array) }} runs-on: ${{ matrix.runs-on }} steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v2 + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 with: node-version: "23.x" registry-url: ${{ inputs.node-registry-url }} - name: Pin NPM Version run: npm install -g npm@8.19.3 - name: Use Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: Install Python Dependencies diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index 7337f505b..f9f9431c6 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -4,27 +4,27 @@ name: deploy-docs on: - push: - branches: - - "main" - tags: - - "*" + push: + branches: + - "main" + tags: + - "*" jobs: - deploy-documentation: - runs-on: ubuntu-latest - steps: - - name: Check out src from Git - uses: actions/checkout@v2 - - name: Get history and tags for SCM versioning to work - run: | - git fetch --prune --unshallow - git fetch --depth=1 origin +refs/tags/*:refs/tags/* - - name: Login to Heroku Container Registry - run: echo ${{ secrets.HEROKU_API_KEY }} | docker login -u ${{ secrets.HEROKU_EMAIL }} --password-stdin registry.heroku.com - - name: Build Docker Image - run: docker build . --file docs/Dockerfile --tag registry.heroku.com/${{ secrets.HEROKU_APP_NAME }}/web - - name: Push Docker Image - run: docker push registry.heroku.com/${{ secrets.HEROKU_APP_NAME }}/web - - name: Deploy - run: HEROKU_API_KEY=${{ secrets.HEROKU_API_KEY }} heroku container:release web --app ${{ secrets.HEROKU_APP_NAME }} + deploy-documentation: + runs-on: ubuntu-latest + steps: + - name: Check out src from Git + uses: actions/checkout@v4 + - name: Get history and tags for SCM versioning to work + run: | + git fetch --prune --unshallow + git fetch --depth=1 origin +refs/tags/*:refs/tags/* + - name: Login to Heroku Container Registry + run: echo ${{ secrets.HEROKU_API_KEY }} | docker login -u ${{ secrets.HEROKU_EMAIL }} --password-stdin registry.heroku.com + - name: Build Docker Image + run: docker build . --file docs/Dockerfile --tag registry.heroku.com/${{ secrets.HEROKU_APP_NAME }}/web + - name: Push Docker Image + run: docker push registry.heroku.com/${{ secrets.HEROKU_APP_NAME }}/web + - name: Deploy + run: HEROKU_API_KEY=${{ secrets.HEROKU_API_KEY }} heroku container:release web --app ${{ secrets.HEROKU_APP_NAME }} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index e9271cbd5..8e523ce04 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -4,17 +4,17 @@ name: publish on: - release: - types: [published] + release: + types: [published] jobs: - publish: - uses: ./.github/workflows/.hatch-run.yml - with: - job-name: "publish" - hatch-run: "publish" - node-registry-url: "https://registry.npmjs.org" - secrets: - node-auth-token: ${{ secrets.NODE_AUTH_TOKEN }} - pypi-username: ${{ secrets.PYPI_USERNAME }} - pypi-password: ${{ secrets.PYPI_PASSWORD }} + publish: + uses: ./.github/workflows/.hatch-run.yml + with: + job-name: "publish" + hatch-run: "publish" + node-registry-url: "https://registry.npmjs.org" + secrets: + node-auth-token: ${{ secrets.NODE_AUTH_TOKEN }} + pypi-username: ${{ secrets.PYPI_USERNAME }} + pypi-password: ${{ secrets.PYPI_PASSWORD }} diff --git a/src/py/reactpy/tests/test_backend/test_all.py b/src/py/reactpy/tests/test_backend/test_all.py index 9a1440d52..cd2f371f5 100644 --- a/src/py/reactpy/tests/test_backend/test_all.py +++ b/src/py/reactpy/tests/test_backend/test_all.py @@ -1,4 +1,3 @@ -import sys from collections.abc import MutableMapping import pytest @@ -107,17 +106,13 @@ def ShowScope(): assert isinstance(scope.current, MutableMapping) -@pytest.mark.skipIf( - sys.platform == "darwin", - reason="Tornado and Flask backends are currently buggy on MacOS.", -) async def test_use_location(display: DisplayFixture): location = reactpy.Ref() @poll async def poll_location(): """This needs to be async to allow the server to respond""" - return location.current + return getattr(location, "current", None) @reactpy.component def ShowRoute(): From f70bccd35dd7704d25f085bd9de294ecbf39f72a Mon Sep 17 00:00:00 2001 From: Josh <59149404+joshbmair@users.noreply.github.com> Date: Tue, 29 Oct 2024 05:35:19 -0500 Subject: [PATCH 11/16] Move `reactpy.backend.hooks` module into `reactpy.core.hooks` (#1210) --- docs/source/about/changelog.rst | 3 ++ src/py/reactpy/reactpy/__init__.py | 4 +- src/py/reactpy/reactpy/backend/flask.py | 4 +- src/py/reactpy/reactpy/backend/hooks.py | 41 ++++++++++++++------- src/py/reactpy/reactpy/backend/sanic.py | 4 +- src/py/reactpy/reactpy/backend/starlette.py | 4 +- src/py/reactpy/reactpy/backend/tornado.py | 4 +- src/py/reactpy/reactpy/core/hooks.py | 26 ++++++++++++- 8 files changed, 67 insertions(+), 23 deletions(-) diff --git a/docs/source/about/changelog.rst b/docs/source/about/changelog.rst index 9fc13e015..b79529acc 100644 --- a/docs/source/about/changelog.rst +++ b/docs/source/about/changelog.rst @@ -40,12 +40,15 @@ Unreleased fragment to conditionally render an element by writing ``something if condition else html._()``. Now you can simply write ``something if condition else None``. +- :pull:`1210` - Move hooks from ``reactpy.backend.hooks`` into ``reactpy.core.hooks``. **Deprecated** - :pull:`1171` - The ``Stop`` exception. Recent releases of ``anyio`` have made this exception difficult to use since it now raises an ``ExceptionGroup``. This exception was primarily used for internal testing purposes and so is now deprecated. +- :pull:`1210` - Deprecate ``reactpy.backend.hooks`` since the hooks have been moved into + ``reactpy.core.hooks``. v1.0.2 diff --git a/src/py/reactpy/reactpy/__init__.py b/src/py/reactpy/reactpy/__init__.py index 49e357441..c47142cd8 100644 --- a/src/py/reactpy/reactpy/__init__.py +++ b/src/py/reactpy/reactpy/__init__.py @@ -1,5 +1,4 @@ from reactpy import backend, config, html, logging, sample, svg, types, web, widgets -from reactpy.backend.hooks import use_connection, use_location, use_scope from reactpy.backend.utils import run from reactpy.core import hooks from reactpy.core.component import component @@ -7,12 +6,15 @@ from reactpy.core.hooks import ( create_context, use_callback, + use_connection, use_context, use_debug_value, use_effect, + use_location, use_memo, use_reducer, use_ref, + use_scope, use_state, ) from reactpy.core.layout import Layout diff --git a/src/py/reactpy/reactpy/backend/flask.py b/src/py/reactpy/reactpy/backend/flask.py index faa979aa9..4401fb6f7 100644 --- a/src/py/reactpy/reactpy/backend/flask.py +++ b/src/py/reactpy/reactpy/backend/flask.py @@ -35,9 +35,9 @@ safe_client_build_dir_path, safe_web_modules_dir_path, ) -from reactpy.backend.hooks import ConnectionContext -from reactpy.backend.hooks import use_connection as _use_connection from reactpy.backend.types import Connection, Location +from reactpy.core.hooks import ConnectionContext +from reactpy.core.hooks import use_connection as _use_connection from reactpy.core.serve import serve_layout from reactpy.core.types import ComponentType, RootComponentConstructor from reactpy.utils import Ref diff --git a/src/py/reactpy/reactpy/backend/hooks.py b/src/py/reactpy/reactpy/backend/hooks.py index ee4ce1b5c..ef1b4a5cb 100644 --- a/src/py/reactpy/reactpy/backend/hooks.py +++ b/src/py/reactpy/reactpy/backend/hooks.py @@ -1,30 +1,45 @@ -from __future__ import annotations +from __future__ import annotations # nocov -from collections.abc import MutableMapping -from typing import Any +from collections.abc import MutableMapping # nocov +from typing import Any # nocov -from reactpy.backend.types import Connection, Location -from reactpy.core.hooks import create_context, use_context -from reactpy.core.types import Context +from reactpy._warnings import warn # nocov +from reactpy.backend.types import Connection, Location # nocov +from reactpy.core.hooks import ConnectionContext, use_context # nocov -# backend implementations should establish this context at the root of an app -ConnectionContext: Context[Connection[Any] | None] = create_context(None) - -def use_connection() -> Connection[Any]: +def use_connection() -> Connection[Any]: # nocov """Get the current :class:`~reactpy.backend.types.Connection`.""" + warn( + "The module reactpy.backend.hooks has been deprecated and will be deleted in the future. ", + "Call reactpy.use_connection instead.", + DeprecationWarning, + ) + conn = use_context(ConnectionContext) - if conn is None: # nocov + if conn is None: msg = "No backend established a connection." raise RuntimeError(msg) return conn -def use_scope() -> MutableMapping[str, Any]: +def use_scope() -> MutableMapping[str, Any]: # nocov """Get the current :class:`~reactpy.backend.types.Connection`'s scope.""" + warn( + "The module reactpy.backend.hooks has been deprecated and will be deleted in the future. ", + "Call reactpy.use_scope instead.", + DeprecationWarning, + ) + return use_connection().scope -def use_location() -> Location: +def use_location() -> Location: # nocov """Get the current :class:`~reactpy.backend.types.Connection`'s location.""" + warn( + "The module reactpy.backend.hooks has been deprecated and will be deleted in the future. ", + "Call reactpy.use_location instead.", + DeprecationWarning, + ) + return use_connection().location diff --git a/src/py/reactpy/reactpy/backend/sanic.py b/src/py/reactpy/reactpy/backend/sanic.py index 76eb0423e..d272fb4cf 100644 --- a/src/py/reactpy/reactpy/backend/sanic.py +++ b/src/py/reactpy/reactpy/backend/sanic.py @@ -24,9 +24,9 @@ safe_web_modules_dir_path, serve_with_uvicorn, ) -from reactpy.backend.hooks import ConnectionContext -from reactpy.backend.hooks import use_connection as _use_connection from reactpy.backend.types import Connection, Location +from reactpy.core.hooks import ConnectionContext +from reactpy.core.hooks import use_connection as _use_connection from reactpy.core.layout import Layout from reactpy.core.serve import RecvCoroutine, SendCoroutine, Stop, serve_layout from reactpy.core.types import RootComponentConstructor diff --git a/src/py/reactpy/reactpy/backend/starlette.py b/src/py/reactpy/reactpy/backend/starlette.py index 9bc68db47..20e2b4478 100644 --- a/src/py/reactpy/reactpy/backend/starlette.py +++ b/src/py/reactpy/reactpy/backend/starlette.py @@ -24,10 +24,10 @@ read_client_index_html, serve_with_uvicorn, ) -from reactpy.backend.hooks import ConnectionContext -from reactpy.backend.hooks import use_connection as _use_connection from reactpy.backend.types import Connection, Location from reactpy.config import REACTPY_WEB_MODULES_DIR +from reactpy.core.hooks import ConnectionContext +from reactpy.core.hooks import use_connection as _use_connection from reactpy.core.layout import Layout from reactpy.core.serve import RecvCoroutine, SendCoroutine, serve_layout from reactpy.core.types import RootComponentConstructor diff --git a/src/py/reactpy/reactpy/backend/tornado.py b/src/py/reactpy/reactpy/backend/tornado.py index 8f540ddb4..bd339c5b9 100644 --- a/src/py/reactpy/reactpy/backend/tornado.py +++ b/src/py/reactpy/reactpy/backend/tornado.py @@ -24,10 +24,10 @@ CommonOptions, read_client_index_html, ) -from reactpy.backend.hooks import ConnectionContext -from reactpy.backend.hooks import use_connection as _use_connection from reactpy.backend.types import Connection, Location from reactpy.config import REACTPY_WEB_MODULES_DIR +from reactpy.core.hooks import ConnectionContext +from reactpy.core.hooks import use_connection as _use_connection from reactpy.core.layout import Layout from reactpy.core.serve import serve_layout from reactpy.core.types import ComponentConstructor diff --git a/src/py/reactpy/reactpy/core/hooks.py b/src/py/reactpy/reactpy/core/hooks.py index 640cbf14c..0ece8cccf 100644 --- a/src/py/reactpy/reactpy/core/hooks.py +++ b/src/py/reactpy/reactpy/core/hooks.py @@ -1,7 +1,7 @@ from __future__ import annotations import asyncio -from collections.abc import Coroutine, Sequence +from collections.abc import Coroutine, MutableMapping, Sequence from logging import getLogger from types import FunctionType from typing import ( @@ -17,6 +17,7 @@ from typing_extensions import TypeAlias +from reactpy.backend.types import Connection, Location from reactpy.config import REACTPY_DEBUG_MODE from reactpy.core._life_cycle_hook import current_hook from reactpy.core.types import Context, Key, State, VdomDict @@ -248,6 +249,29 @@ def use_context(context: Context[_Type]) -> _Type: return provider.value +# backend implementations should establish this context at the root of an app +ConnectionContext: Context[Connection[Any] | None] = create_context(None) + + +def use_connection() -> Connection[Any]: + """Get the current :class:`~reactpy.backend.types.Connection`.""" + conn = use_context(ConnectionContext) + if conn is None: # nocov + msg = "No backend established a connection." + raise RuntimeError(msg) + return conn + + +def use_scope() -> MutableMapping[str, Any]: + """Get the current :class:`~reactpy.backend.types.Connection`'s scope.""" + return use_connection().scope + + +def use_location() -> Location: + """Get the current :class:`~reactpy.backend.types.Connection`'s location.""" + return use_connection().location + + class _ContextProvider(Generic[_Type]): def __init__( self, From 0e4432f11efb4baf9276059ede688631ec4af104 Mon Sep 17 00:00:00 2001 From: ShawnCrawley-NOAA Date: Tue, 29 Oct 2024 05:09:34 -0600 Subject: [PATCH 12/16] Fixes needless custom component recreation (#1195) (#1224) --- docs/source/about/changelog.rst | 1 + src/js/packages/@reactpy/client/src/components.tsx | 4 ++-- src/py/reactpy/reactpy/web/templates/react.js | 5 +++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/source/about/changelog.rst b/docs/source/about/changelog.rst index b79529acc..04d426a6b 100644 --- a/docs/source/about/changelog.rst +++ b/docs/source/about/changelog.rst @@ -23,6 +23,7 @@ Unreleased - :pull:`1118` - `module_from_template` is broken with a recent release of `requests` - :pull:`1131` - `module_from_template` did not work when using Flask backend - :pull:`1200` - Fixed `UnicodeDecodeError` when using `reactpy.web.export` +- :pull:`1224` - Fixes needless unmounting of JavaScript components during each ReactPy render. **Added** diff --git a/src/js/packages/@reactpy/client/src/components.tsx b/src/js/packages/@reactpy/client/src/components.tsx index 728c4cec7..2319f81c7 100644 --- a/src/js/packages/@reactpy/client/src/components.tsx +++ b/src/js/packages/@reactpy/client/src/components.tsx @@ -177,7 +177,7 @@ function useForceUpdate() { function useImportSource(model: ReactPyVdom): MutableRefObject { const vdomImportSource = model.importSource; - + const vdomImportSourceJsonString = JSON.stringify(vdomImportSource); const mountPoint = useRef(null); const client = React.useContext(ClientContext); const [binding, setBinding] = useState(null); @@ -203,7 +203,7 @@ function useImportSource(model: ReactPyVdom): MutableRefObject { binding.unmount(); } }; - }, [client, vdomImportSource, setBinding, mountPoint.current]); + }, [client, vdomImportSourceJsonString, setBinding, mountPoint.current]); // this effect must run every time in case the model has changed useEffect(() => { diff --git a/src/py/reactpy/reactpy/web/templates/react.js b/src/py/reactpy/reactpy/web/templates/react.js index 5c6a45743..366be4fd0 100644 --- a/src/py/reactpy/reactpy/web/templates/react.js +++ b/src/py/reactpy/reactpy/web/templates/react.js @@ -17,11 +17,12 @@ export default ({ children, ...props }) => { }; export function bind(node, config) { + const root = ReactDOM.createRoot(node); return { create: (component, props, children) => React.createElement(component, wrapEventHandlers(props), ...children), - render: (element) => ReactDOM.render(element, node), - unmount: () => ReactDOM.unmountComponentAtNode(node), + render: (element) => root.render(element), + unmount: () => root.unmount() }; } From 69775668f6d9995908418e8af270cd705c1ca9f1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 29 Oct 2024 04:25:43 -0700 Subject: [PATCH 13/16] Bump vite from 3.2.8 to 3.2.11 in /src/js (#1235) Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 3.2.8 to 3.2.11. - [Release notes](https://github.com/vitejs/vite/releases) - [Changelog](https://github.com/vitejs/vite/blob/v3.2.11/packages/vite/CHANGELOG.md) - [Commits](https://github.com/vitejs/vite/commits/v3.2.11/packages/vite) --- updated-dependencies: - dependency-name: vite dependency-type: direct:development ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/js/app/package.json | 2 +- src/js/package-lock.json | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/js/app/package.json b/src/js/app/package.json index 55a42fd66..cecc15083 100644 --- a/src/js/app/package.json +++ b/src/js/app/package.json @@ -12,7 +12,7 @@ "@types/react": "^17.0", "@types/react-dom": "^17.0", "typescript": "^4.9.5", - "vite": "^3.2.8" + "vite": "^3.2.11" }, "repository": { "type": "git", diff --git a/src/js/package-lock.json b/src/js/package-lock.json index 91b7f302c..8a3ed5aa9 100644 --- a/src/js/package-lock.json +++ b/src/js/package-lock.json @@ -28,7 +28,7 @@ "@types/react": "^17.0", "@types/react-dom": "^17.0", "typescript": "^4.9.5", - "vite": "^3.2.8" + "vite": "^3.2.11" } }, "app/node_modules/@reactpy/client": { @@ -3328,9 +3328,9 @@ } }, "node_modules/vite": { - "version": "3.2.8", - "resolved": "https://registry.npmjs.org/vite/-/vite-3.2.8.tgz", - "integrity": "sha512-EtQU16PLIJpAZol2cTLttNP1mX6L0SyI0pgQB1VOoWeQnMSvtiwovV3D6NcjN8CZQWWyESD2v5NGnpz5RvgOZA==", + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/vite/-/vite-3.2.11.tgz", + "integrity": "sha512-K/jGKL/PgbIgKCiJo5QbASQhFiV02X9Jh+Qq0AKCRCRKZtOTVi4t6wh75FDpGf2N9rYOnzH87OEFQNaFy6pdxQ==", "dev": true, "dependencies": { "esbuild": "^0.15.9", @@ -3955,7 +3955,7 @@ "@types/react-dom": "^17.0", "preact": "^10.7.0", "typescript": "^4.9.5", - "vite": "^3.2.8" + "vite": "^3.2.11" }, "dependencies": { "@reactpy/client": { @@ -5888,9 +5888,9 @@ } }, "vite": { - "version": "3.2.8", - "resolved": "https://registry.npmjs.org/vite/-/vite-3.2.8.tgz", - "integrity": "sha512-EtQU16PLIJpAZol2cTLttNP1mX6L0SyI0pgQB1VOoWeQnMSvtiwovV3D6NcjN8CZQWWyESD2v5NGnpz5RvgOZA==", + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/vite/-/vite-3.2.11.tgz", + "integrity": "sha512-K/jGKL/PgbIgKCiJo5QbASQhFiV02X9Jh+Qq0AKCRCRKZtOTVi4t6wh75FDpGf2N9rYOnzH87OEFQNaFy6pdxQ==", "dev": true, "requires": { "esbuild": "^0.15.9", From 2930befd13f3250cbc56f61ee5f061db5c248226 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 29 Oct 2024 04:41:37 -0700 Subject: [PATCH 14/16] Bump vite from 3.2.8 to 3.2.11 in /src/js/app (#1236) Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 3.2.8 to 3.2.11. - [Release notes](https://github.com/vitejs/vite/releases) - [Changelog](https://github.com/vitejs/vite/blob/v3.2.11/packages/vite/CHANGELOG.md) - [Commits](https://github.com/vitejs/vite/commits/v3.2.11/packages/vite) --- updated-dependencies: - dependency-name: vite dependency-type: direct:development ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/js/app/package-lock.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/js/app/package-lock.json b/src/js/app/package-lock.json index adc398279..5af5f0fd8 100644 --- a/src/js/app/package-lock.json +++ b/src/js/app/package-lock.json @@ -13,7 +13,7 @@ "@types/react": "^17.0", "@types/react-dom": "^17.0", "typescript": "^4.9.5", - "vite": "^3.2.8" + "vite": "^3.2.11" } }, "node_modules/@esbuild/android-arm": { @@ -719,9 +719,9 @@ } }, "node_modules/vite": { - "version": "3.2.8", - "resolved": "https://registry.npmjs.org/vite/-/vite-3.2.8.tgz", - "integrity": "sha512-EtQU16PLIJpAZol2cTLttNP1mX6L0SyI0pgQB1VOoWeQnMSvtiwovV3D6NcjN8CZQWWyESD2v5NGnpz5RvgOZA==", + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/vite/-/vite-3.2.11.tgz", + "integrity": "sha512-K/jGKL/PgbIgKCiJo5QbASQhFiV02X9Jh+Qq0AKCRCRKZtOTVi4t6wh75FDpGf2N9rYOnzH87OEFQNaFy6pdxQ==", "dev": true, "dependencies": { "esbuild": "^0.15.9", @@ -1177,9 +1177,9 @@ "dev": true }, "vite": { - "version": "3.2.8", - "resolved": "https://registry.npmjs.org/vite/-/vite-3.2.8.tgz", - "integrity": "sha512-EtQU16PLIJpAZol2cTLttNP1mX6L0SyI0pgQB1VOoWeQnMSvtiwovV3D6NcjN8CZQWWyESD2v5NGnpz5RvgOZA==", + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/vite/-/vite-3.2.11.tgz", + "integrity": "sha512-K/jGKL/PgbIgKCiJo5QbASQhFiV02X9Jh+Qq0AKCRCRKZtOTVi4t6wh75FDpGf2N9rYOnzH87OEFQNaFy6pdxQ==", "dev": true, "requires": { "esbuild": "^0.15.9", From 84cfc5606f54784fe4367cf1fc4fd59b1daf4b71 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 29 Oct 2024 04:58:00 -0700 Subject: [PATCH 15/16] Bump braces from 3.0.2 to 3.0.3 in /src/js (#1238) Bumps [braces](https://github.com/micromatch/braces) from 3.0.2 to 3.0.3. - [Changelog](https://github.com/micromatch/braces/blob/master/CHANGELOG.md) - [Commits](https://github.com/micromatch/braces/compare/3.0.2...3.0.3) --- updated-dependencies: - dependency-name: braces dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Mark Bakhit --- src/js/package-lock.json | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/js/package-lock.json b/src/js/package-lock.json index 8a3ed5aa9..83d0d5c08 100644 --- a/src/js/package-lock.json +++ b/src/js/package-lock.json @@ -664,12 +664,12 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -1581,9 +1581,9 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "dependencies": { "to-regex-range": "^5.0.1" @@ -4058,12 +4058,12 @@ } }, "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "requires": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" } }, "call-bind": { @@ -4676,9 +4676,9 @@ } }, "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "requires": { "to-regex-range": "^5.0.1" From 1dcba7cb1fdcaafe751e1e2e3a666ae54430603d Mon Sep 17 00:00:00 2001 From: Dennis <47893482+DennisHC@users.noreply.github.com> Date: Tue, 29 Oct 2024 05:07:02 -0700 Subject: [PATCH 16/16] Added checked: element.checked to INPUT in elementConverters (#1126) --- docs/source/about/changelog.rst | 9 +++++---- src/js/packages/event-to-object/src/index.ts | 5 ++++- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/docs/source/about/changelog.rst b/docs/source/about/changelog.rst index 04d426a6b..325481f9a 100644 --- a/docs/source/about/changelog.rst +++ b/docs/source/about/changelog.rst @@ -20,15 +20,16 @@ Unreleased **Fixed** -- :pull:`1118` - `module_from_template` is broken with a recent release of `requests` -- :pull:`1131` - `module_from_template` did not work when using Flask backend -- :pull:`1200` - Fixed `UnicodeDecodeError` when using `reactpy.web.export` +- :pull:`1118` - ``module_from_template`` is broken with a recent release of ``requests`` +- :pull:`1131` - ``module_from_template`` did not work when using Flask backend +- :pull:`1200` - Fixed ``UnicodeDecodeError`` when using ``reactpy.web.export`` - :pull:`1224` - Fixes needless unmounting of JavaScript components during each ReactPy render. +- :pull:`1126` - Fixed missing ``event["target"]["checked"]`` on checkbox inputs **Added** - :pull:`1165` - Allow concurrently rendering discrete component trees - enable this - experimental feature by setting `REACTPY_ASYNC_RENDERING=true`. This improves + experimental feature by setting ``REACTPY_ASYNC_RENDERING=true``. This improves the overall responsiveness of your app in situations where larger renders would otherwise block smaller renders from executing. diff --git a/src/js/packages/event-to-object/src/index.ts b/src/js/packages/event-to-object/src/index.ts index 9a40a2128..22fb7154d 100644 --- a/src/js/packages/event-to-object/src/index.ts +++ b/src/js/packages/event-to-object/src/index.ts @@ -303,7 +303,10 @@ const elementConverters: { [key: string]: (element: any) => any } = { FORM: (element: HTMLFormElement) => ({ elements: Array.from(element.elements).map(convertElement), }), - INPUT: (element: HTMLInputElement) => ({ value: element.value }), + INPUT: (element: HTMLInputElement) => ({ + value: element.value, + checked: element.checked, + }), METER: (element: HTMLMeterElement) => ({ value: element.value }), OPTION: (element: HTMLOptionElement) => ({ value: element.value }), OUTPUT: (element: HTMLOutputElement) => ({ value: element.value }),