blu-react 0.0.2__tar.gz → 0.0.3__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.
- blu_react-0.0.3/CHANGELOG.md +18 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/PKG-INFO +2 -3
- {blu_react-0.0.2 → blu_react-0.0.3}/docs/_includes/client-element-children.rst +1 -1
- {blu_react-0.0.2 → blu_react-0.0.3}/docs/_includes/client-side-rendering-notes.rst +18 -6
- {blu_react-0.0.2 → blu_react-0.0.3}/docs/_includes/iterables-must-use-keys-note.rst +1 -1
- {blu_react-0.0.2 → blu_react-0.0.3}/docs/api-reference/blu.html.rst +2 -1
- {blu_react-0.0.2 → blu_react-0.0.3}/docs/api-reference/cli.rst +1 -1
- {blu_react-0.0.2 → blu_react-0.0.3}/docs/api-reference/file-conventions.rst +96 -27
- {blu_react-0.0.2 → blu_react-0.0.3}/docs/api-reference/index.rst +1 -1
- blu_react-0.0.3/docs/api-reference/js.rst +35 -0
- blu_react-0.0.3/docs/api-reference/pyodide.rst +36 -0
- blu_react-0.0.3/docs/appendices/choosing-an-interpreter.rst +28 -0
- blu_react-0.0.3/docs/appendices/index.rst +10 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/docs/conf.py +2 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/docs/contributing.rst +4 -2
- {blu_react-0.0.2 → blu_react-0.0.3}/docs/index.rst +1 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/docs/install.rst +0 -2
- {blu_react-0.0.2 → blu_react-0.0.3}/docs/quickstart.rst +2 -2
- blu_react-0.0.3/docs/requirements.txt +2 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/docs/user-guide/client-side-rendering.rst +4 -4
- {blu_react-0.0.2 → blu_react-0.0.3}/docs/user-guide/creating-pages.rst +3 -3
- {blu_react-0.0.2 → blu_react-0.0.3}/docs/user-guide/deploying-your-app.rst +1 -1
- {blu_react-0.0.2 → blu_react-0.0.3}/docs/user-guide/routing.rst +8 -10
- {blu_react-0.0.2 → blu_react-0.0.3}/docs/user-guide/static-files.rst +1 -1
- {blu_react-0.0.2 → blu_react-0.0.3}/pyproject.toml +3 -2
- blu_react-0.0.3/scripts/profile_asgi_request.py +176 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/src/blu/__init__.py +2 -3
- {blu_react-0.0.2 → blu_react-0.0.3}/src/blu/_app/__init__.py +28 -17
- {blu_react-0.0.2 → blu_react-0.0.3}/src/blu/_app/render.py +29 -38
- {blu_react-0.0.2 → blu_react-0.0.3}/src/blu/_app/router.py +58 -28
- blu_react-0.0.3/src/blu/_blu_static_files/micropython-bootstrap.js +65 -0
- blu_react-0.0.3/src/blu/_blu_static_files/micropython.mjs +6711 -0
- blu_react-0.0.3/src/blu/_blu_static_files/micropython.wasm +0 -0
- blu_react-0.0.3/src/blu/_blu_static_files/pyodide-bootstrap.js +26 -0
- {blu_react-0.0.2/src/blu → blu_react-0.0.3/src/blu/_blu_static_files}/util.js +23 -8
- blu_react-0.0.3/src/blu/_client_main/micropython.py +143 -0
- blu_react-0.0.3/src/blu/_client_main/pyodide.py +38 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/src/blu/_hooks.py +115 -126
- {blu_react-0.0.2 → blu_react-0.0.3}/src/blu/_http.py +3 -3
- blu_react-0.0.3/src/blu/_mPickle/manifest.py +40 -0
- blu_react-0.0.3/src/blu/_mPickle/mpickle/__init__.py +61 -0
- blu_react-0.0.3/src/blu/_mPickle/mpickle/_compat_pickle.py +270 -0
- blu_react-0.0.3/src/blu/_mPickle/mpickle/codecs.py +106 -0
- blu_react-0.0.3/src/blu/_mPickle/mpickle/copyreg.py +304 -0
- blu_react-0.0.3/src/blu/_mPickle/mpickle/itertools.py +119 -0
- blu_react-0.0.3/src/blu/_mPickle/mpickle/mpickle.py +2695 -0
- blu_react-0.0.3/src/blu/_mPickle/mpickle/ubytesio.py +38 -0
- blu_react-0.0.3/src/blu/_micropython/abc.py +23 -0
- blu_react-0.0.3/src/blu/_micropython/typing.py +36 -0
- blu_react-0.0.3/src/blu/_micropython/utils.py +121 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/src/blu/_nodes.py +55 -55
- {blu_react-0.0.2 → blu_react-0.0.3}/src/blu/_server_functions.py +50 -32
- {blu_react-0.0.2 → blu_react-0.0.3}/src/blu/_settings.py +2 -2
- {blu_react-0.0.2 → blu_react-0.0.3}/src/blu/_utils/__init__.py +1 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/src/blu/_utils/asgi.py +8 -1
- {blu_react-0.0.2 → blu_react-0.0.3}/src/blu/_utils/asyncio.py +23 -19
- blu_react-0.0.3/src/blu/_utils/client.py +10 -0
- blu_react-0.0.3/src/blu/html.py +270 -0
- blu_react-0.0.3/tests/apps/def_extra_query_params/__default__.py +2 -0
- blu_react-0.0.3/tests/apps/def_pos_only_path_param/__default__.py +2 -0
- blu_react-0.0.3/tests/apps/def_query/__default__.py +2 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/def_query_kwarg/__default__.py +1 -1
- blu_react-0.0.3/tests/apps/def_query_params_default/__default__.py +2 -0
- blu_react-0.0.3/tests/apps/def_route_and_query/_a_/_b_/__default__.py +2 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/e2e/routing/_a_/__index__.py +1 -1
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/e2e/use_effect/__index__.py +6 -2
- blu_react-0.0.3/tests/apps/e2e_settings/__index__.py +19 -0
- blu_react-0.0.3/tests/apps/e2e_settings/__settings__.py +1 -0
- {blu_react-0.0.2/tests/apps/e2e_settings → blu_react-0.0.3/tests/apps/e2e_settings_pyodide}/__settings__.py +2 -0
- blu_react-0.0.3/tests/apps/e2e_simple_app/__index__.py +5 -0
- blu_react-0.0.3/tests/apps/e2e_simple_app/a/module.py +3 -0
- blu_react-0.0.3/tests/apps/index_query_abc/__index__.py +2 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/index_query_kwargs/__index__.py +1 -1
- blu_react-0.0.3/tests/apps/index_route_and_query/_a_/_b_/__index__.py +2 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/conftest.py +34 -6
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/fast/file_conventions/special_files/test_default.py +0 -21
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/fast/file_conventions/special_files/test_index.py +0 -21
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/fast/file_conventions/special_files/test_settings.py +2 -8
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/test_e2e.py +53 -52
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/utils.py +10 -1
- {blu_react-0.0.2 → blu_react-0.0.3}/uv.lock +20 -5
- blu_react-0.0.2/docs/api-reference/js.rst +0 -35
- blu_react-0.0.2/docs/api-reference/pyscript.rst +0 -38
- blu_react-0.0.2/docs/requirements.txt +0 -1
- blu_react-0.0.2/src/blu/_app/client_main.py +0 -159
- blu_react-0.0.2/src/blu/_utils/client.py +0 -3
- blu_react-0.0.2/src/blu/_utils/typing.py +0 -33
- blu_react-0.0.2/src/blu/html.py +0 -91
- blu_react-0.0.2/tests/apps/def_extra_query_params/__default__.py +0 -2
- blu_react-0.0.2/tests/apps/def_pos_only_path_param/__default__.py +0 -2
- blu_react-0.0.2/tests/apps/def_pos_only_underscore/__default__.py +0 -2
- blu_react-0.0.2/tests/apps/def_query/__default__.py +0 -2
- blu_react-0.0.2/tests/apps/def_query_params_default/__default__.py +0 -2
- blu_react-0.0.2/tests/apps/def_route_and_query/_a_/_b_/__default__.py +0 -2
- blu_react-0.0.2/tests/apps/default_single_underscore/__default__.py +0 -2
- blu_react-0.0.2/tests/apps/e2e/async_effect/__index__.py +0 -45
- blu_react-0.0.2/tests/apps/e2e/client_import/__index__.py +0 -14
- blu_react-0.0.2/tests/apps/index_pos_only_underscore/__index__.py +0 -2
- blu_react-0.0.2/tests/apps/index_query_abc/__index__.py +0 -2
- blu_react-0.0.2/tests/apps/index_route_and_query/_a_/_b_/__index__.py +0 -2
- blu_react-0.0.2/tests/apps/index_single_underscore/__index__.py +0 -2
- {blu_react-0.0.2 → blu_react-0.0.3}/.gitignore +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/.pre-commit-config.yaml +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/.readthedocs.yaml +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/.vscode/launch.json +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/.vscode/settings.json +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/LICENSE +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/README.md +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/docs/Makefile +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/docs/_img/cursor_code_completion.png +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/docs/_img/directly_manipulating_rendered_elements.gif +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/docs/_img/effect_cleanup.gif +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/docs/_img/perform_an_action_immediately_after_rendering.gif +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/docs/_img/responding_to_user_interaction.gif +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/docs/_includes/client-element-call-notes.rst +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/docs/_includes/hook-note.rst +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/docs/_includes/hooks.rst +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/docs/_static/styles.css +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/docs/_templates/layout.html +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/docs/api-reference/blu.rst +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/docs/make.bat +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/docs/user-guide/index.rst +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/src/blu/_cli.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/src/blu/_exceptions.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/src/blu/_utils/json.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/__init__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/app_module_reject/module.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/basic/__index__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/client_false/module.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/client_module/module.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/def_async_handler/__default__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/def_empty_path_param/a/__default__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/def_extra_route_params/__default__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/def_missing_query_params/__default__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/def_missing_route_params/_a_/_b_/_c_/__default__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/default_extra_segment/a/__default__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/default_full_match/a/_b_/c/__default__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/default_incomplete_match/a/b/c/__default__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/default_path_param/__default__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/default_response_ret/__default__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/default_route_params/_a_/_b_/_c_/__default__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/default_specific_priority/_a_/__default__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/default_specific_priority/_b_/c/__default__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/dynamic_non_matching_static/_dynamic_/__index__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/dynamic_non_matching_static/static/__index__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/dynamic_segment/_segment_/__index__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/dynamic_static_not_full_match/_dynamic_/bar/__index__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/dynamic_static_not_full_match/foo/baz/__index__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/e2e/app_pkg_clientside/fail/__index__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/e2e/app_pkg_clientside/fail/element.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/e2e/app_pkg_clientside/fail/module.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/e2e/app_pkg_clientside/success/__index__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/e2e/app_pkg_clientside/success/element.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/e2e/app_pkg_clientside/success/module.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/e2e/dev_server/__index__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/e2e/html_editing_effect/__index__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/e2e/is_client/__index__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/e2e/rendering/__index__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/e2e/routing/_a_/__default__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/e2e/routing/_a_/_b_/__index__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/e2e/routing/_a_/static/__index__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/e2e/server_functions/__index__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/e2e/server_functions/hello_module.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/e2e/server_functions/shared.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/e2e/static_file/_dynamic_path_/hello.txt +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/e2e/unusual_root_nodes/float/__index__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/e2e/unusual_root_nodes/int/__index__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/e2e/unusual_root_nodes/iterable/__index__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/e2e/unusual_root_nodes/key/__index__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/e2e/unusual_root_nodes/none/__index__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/e2e/unusual_root_nodes/str/__index__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/e2e/unusual_root_nodes/tuple/__index__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/e2e/use_ref/__index__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/e2e/use_state/__index__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/e2e/wrong_environment_error/__index__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/e2e/yield_in_tuple/__index__.py +0 -0
- {blu_react-0.0.2/tests/apps/e2e_settings → blu_react-0.0.3/tests/apps/e2e_settings_pyodide}/__index__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/empty_settings/__index__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/empty_settings/__settings__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/index_abc/a/b/c/__index__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/index_async_handler/__index__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/index_dynamic_abc/_a_/_b_/_c_/__index__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/index_extra_route_params/__index__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/index_file_priority/_a_/c/__default__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/index_file_priority/_b_/c/__index__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/index_missing_route_params/_a_/__index__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/index_response/__index__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/leading_underscore/_path/__index__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/literal_segment/path/__index__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/multiple_dynamic/_a_/b/__index__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/multiple_dynamic/_c_/d/__index__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/nested_dynamic_segments/_first_/_second_/__index__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/nested_literal_segments/path/to/view/__index__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/server_function_arbitrary_function_call/server_functions.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/server_function_arbitrary_function_call/server_only_module.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/server_function_csrf/__index__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/server_function_csrf/file.txt +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/server_function_csrf/server_functions.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/server_functions_outside_app/valid.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/settings_below_top_level/foo/__settings__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/settings_multi_client_reqs/__settings__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/settings_one_client_req/__settings__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/static_dynamic_nested/static/_dynamic_/__index__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/static_dynamic_priority/_dynamic_/__index__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/static_dynamic_priority/static/__index__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/static_files/path/to/static/file.txt +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/static_files_dynamic_path/_a_/file.txt +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/top_level_segment/__index__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/apps/trailing_underscore/path_/__index__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/fast/blu/test_ClientElement.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/fast/blu/test_HTMLElement.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/fast/blu/test_Key.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/fast/blu/test_Response.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/fast/blu/test_app.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/fast/blu/test_create_rare_html_element.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/fast/blu/test_html.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/fast/blu/test_is_client.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/fast/blu/test_server.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/fast/file_conventions/_utils.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/fast/file_conventions/directories/test_literal_segment.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/fast/file_conventions/directories/test_route_param_name.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/fast/file_conventions/test_static_files.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/fast/test_cli.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/fast/test_security.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/projects/basic/app/__index__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/projects/quickstart/app/__index__.py +0 -0
- {blu_react-0.0.2 → blu_react-0.0.3}/tests/resources/server_fn_outside_app.py +0 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## v0.0.3 - 2026-10-12
|
|
4
|
+
|
|
5
|
+
_Blu now uses MicroPython by default and no longer uses PyScript. If you are upgrading from v0.0.2, add `INTERPRETER = 'pyodide'` to your `__settings__.py` and remove any references to the `pyscript`._
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Add support for MicroPython in client-side code.
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
|
|
13
|
+
- **Breaking** Use `*` instead of `/` to separate route parameters and query parameters in route handlers.
|
|
14
|
+
- **Breaking** Make MicroPython the default client-side Python interpreter (use previous default interpreter by adding `INTERPRETER = 'pyodide'` to `__settings__.py`).
|
|
15
|
+
|
|
16
|
+
### Removed
|
|
17
|
+
|
|
18
|
+
- **Breaking** Remove support for async callbacks in `blu.use_effect()`.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: blu-react
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.3
|
|
4
4
|
Summary: A full stack React framework for Python
|
|
5
5
|
Project-URL: Homepage, https://github.com/johnlarson/blu
|
|
6
6
|
Project-URL: Documentation, https://blu-react.readthedocs.io
|
|
@@ -11,7 +11,6 @@ License-File: LICENSE
|
|
|
11
11
|
Classifier: Operating System :: OS Independent
|
|
12
12
|
Classifier: Programming Language :: Python :: 3
|
|
13
13
|
Requires-Python: >=3.14
|
|
14
|
-
Requires-Dist: aiofiles
|
|
15
14
|
Requires-Dist: uvicorn
|
|
16
15
|
Description-Content-Type: text/markdown
|
|
17
16
|
|
|
@@ -51,7 +51,7 @@ A child of an HTML element can be any of the following types:
|
|
|
51
51
|
- A :py:class:`int`. This renders as a text node whose text is the :py:class:`str` representation of the integer.
|
|
52
52
|
- A :py:class:`float`. This renders as a text node whose text is the :py:class:`str` representation of the float.
|
|
53
53
|
- An :py:class:`Iterable <collections.abc.Iterable>` of valid children. This renders as all the child nodes contained in the :py:class:`Iterable <collections.abc.Iterable>`.
|
|
54
|
-
- A :class:`blu.ClientElement` (see :ref:`Client-Side Rendering`).
|
|
54
|
+
- A :class:`blu.ClientElement` (see :ref:`user-guide/client-side-rendering:Client-Side Rendering`).
|
|
55
55
|
- A :class:`blu.Key`.
|
|
56
56
|
|
|
57
57
|
.. code-block:: python
|
|
@@ -41,6 +41,17 @@
|
|
|
41
41
|
return p['Hello, World!']
|
|
42
42
|
|
|
43
43
|
|
|
44
|
+
.. note::
|
|
45
|
+
|
|
46
|
+
By default, Python code that runs on the client is run by the MicroPython interpreter. This means some features of Python are unavailable to modules that are used client-side. You can choose to use a more fully-featured but slower-loading Python interpreter called Pyodide by adding the following to ``app/__settings__.py``:
|
|
47
|
+
|
|
48
|
+
.. code-block:: python
|
|
49
|
+
:caption: app/__settings__.py
|
|
50
|
+
|
|
51
|
+
INTERPRETER = 'pyodide'
|
|
52
|
+
|
|
53
|
+
For more information, see :doc:`/appendices/choosing-an-interpreter`
|
|
54
|
+
|
|
44
55
|
.. note::
|
|
45
56
|
|
|
46
57
|
Client-side code runs in a different environment than server-side code. If your client-side code uses an external library, make sure it is installed in the client environment by adding it to the list of client dependencies in ``app/__settings__.py`` (if the ``__settings__.py`` doesn't exist, create it)::
|
|
@@ -52,7 +63,7 @@
|
|
|
52
63
|
.. code-block:: python
|
|
53
64
|
:caption: app/__index__.py
|
|
54
65
|
|
|
55
|
-
import
|
|
66
|
+
import base64
|
|
56
67
|
from blu import client
|
|
57
68
|
|
|
58
69
|
__client__ = True
|
|
@@ -64,15 +75,16 @@
|
|
|
64
75
|
|
|
65
76
|
@client
|
|
66
77
|
def MyClientElement():
|
|
67
|
-
return
|
|
68
|
-
|
|
78
|
+
return div[
|
|
79
|
+
p['Message: Hello, World!'],
|
|
80
|
+
p['Base64-encoded:', base64.encode('Hello, World!')],
|
|
69
81
|
]
|
|
70
82
|
|
|
71
83
|
|
|
72
84
|
.. code-block:: python
|
|
73
85
|
:caption: app/__settings__.py
|
|
74
86
|
|
|
75
|
-
CLIENT_REQUIREMENTS = ['
|
|
87
|
+
CLIENT_REQUIREMENTS = ['base64']
|
|
76
88
|
|
|
77
89
|
|
|
78
90
|
.. note::
|
|
@@ -86,7 +98,7 @@
|
|
|
86
98
|
from blu import client
|
|
87
99
|
from blu.html import button
|
|
88
100
|
|
|
89
|
-
from
|
|
101
|
+
from js import window
|
|
90
102
|
|
|
91
103
|
__client__ = True
|
|
92
104
|
|
|
@@ -111,7 +123,7 @@
|
|
|
111
123
|
from blu.html import button
|
|
112
124
|
|
|
113
125
|
if is_client:
|
|
114
|
-
from
|
|
126
|
+
from js import window
|
|
115
127
|
|
|
116
128
|
__client__ = True
|
|
117
129
|
|
|
@@ -56,4 +56,4 @@
|
|
|
56
56
|
# Right.
|
|
57
57
|
div['Hello, Ana! Hello, Bill! Hello, Charlotte!']
|
|
58
58
|
|
|
59
|
-
The rationale here is that, in :ref:`client-side rendering <Client-Side Rendering>`, items in a sequence may be moved around in response to user interaction. Giving keys to these items allows React to maintain state and render efficiently even when an item's position in a sequence changes.
|
|
59
|
+
The rationale here is that, in :ref:`client-side rendering <user-guide/client-side-rendering:Client-Side Rendering>`, items in a sequence may be moved around in response to user interaction. Giving keys to these items allows React to maintain state and render efficiently even when an item's position in a sequence changes.
|
|
@@ -15,4 +15,4 @@ The deveopment server will automatically find an available port to run on, and o
|
|
|
15
15
|
|
|
16
16
|
INFO: Uvicorn running on http://127.0.0.1:50227 (Press CTRL+C to quit)
|
|
17
17
|
|
|
18
|
-
Don't run the development server in production. See :ref:`Deploying Your App` for details on how to deploy an app to a production environment.
|
|
18
|
+
Don't run the development server in production. See :ref:`user-guide/deploying-your-app:Deploying Your App` for details on how to deploy an app to a production environment.
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
File Conventions
|
|
2
2
|
================
|
|
3
3
|
|
|
4
|
-
A Blu app is defined by the :ref:`special files <Special Files>` under its ``app/`` directory. The ``app/`` directory should be placed in the project root (this is the working directory where you run the development server using the ``blu`` command).
|
|
4
|
+
A Blu app is defined by the :ref:`special files <api-reference/file-conventions:Special Files>` under its ``app/`` directory. The ``app/`` directory should be placed in the project root (this is the working directory where you run the development server using the ``blu`` command).
|
|
5
5
|
|
|
6
|
-
Note that some special files' behavior is influenced by :ref:`the directories in their paths <Directories>`, relative to the ``app/`` directory.
|
|
6
|
+
Note that some special files' behavior is influenced by :ref:`the directories in their paths <api-reference/file-conventions:Directories>`, relative to the ``app/`` directory.
|
|
7
7
|
|
|
8
|
-
You can also put :ref:`static files <Static Files>` in the ``app/`` directory.
|
|
8
|
+
You can also put :ref:`static files <api-reference/file-conventions:Static Files>` in the ``app/`` directory.
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
Directories
|
|
@@ -92,10 +92,10 @@ Handles a request whose full URL matches all directories in the path to this fil
|
|
|
92
92
|
/foo/some/other/path
|
|
93
93
|
/foo/bar/extra/segments
|
|
94
94
|
|
|
95
|
-
|
|
96
|
-
^^^^^^^^^^^^^^^^^^^
|
|
95
|
+
An __index__.py file should have the following top-level function:
|
|
97
96
|
|
|
98
97
|
.. py:function:: __page__(***url) -> blu.Node | blu.Response
|
|
98
|
+
:no-index:
|
|
99
99
|
|
|
100
100
|
Handle a request whose URL path is matched by this file.
|
|
101
101
|
|
|
@@ -105,7 +105,7 @@ Top-level functions
|
|
|
105
105
|
from blu.html import p
|
|
106
106
|
|
|
107
107
|
|
|
108
|
-
def __page__(slug,
|
|
108
|
+
def __page__(slug, *, q):
|
|
109
109
|
return (
|
|
110
110
|
p['The slug value is: ', slug],
|
|
111
111
|
p['The query param value is: ', q],
|
|
@@ -148,11 +148,10 @@ Handles a request for which the directories in the path to this file from the ``
|
|
|
148
148
|
/
|
|
149
149
|
/hello
|
|
150
150
|
|
|
151
|
-
|
|
152
|
-
^^^^^^^^^^^^^^^^^^^
|
|
153
|
-
|
|
151
|
+
A __default__.py file should have the following top-level function:
|
|
154
152
|
|
|
155
153
|
.. py:function:: __page__(***url) -> blu.Node | blu.Response
|
|
154
|
+
:no-index:
|
|
156
155
|
|
|
157
156
|
Handle a request whose URL path is matched by this file.
|
|
158
157
|
|
|
@@ -162,7 +161,7 @@ Top-level functions
|
|
|
162
161
|
from blu.html import p
|
|
163
162
|
|
|
164
163
|
|
|
165
|
-
def __page__(slug, path__,
|
|
164
|
+
def __page__(slug, path__, *, q):
|
|
166
165
|
return (
|
|
167
166
|
p['The slug value is: ', slug],
|
|
168
167
|
p['The remaining path is: ', path],
|
|
@@ -189,14 +188,14 @@ __settings__.py
|
|
|
189
188
|
|
|
190
189
|
Configuration for your Blu app.
|
|
191
190
|
|
|
192
|
-
Should be placed in the root of the ``app/`` directory, i.e. the app directory should be the immediate parent of __settings__.py.
|
|
193
|
-
|
|
194
191
|
.. code-block:: python
|
|
195
192
|
:caption: app/__settings__.py
|
|
196
193
|
|
|
194
|
+
INTERPRETER = 'pyodide'
|
|
195
|
+
|
|
197
196
|
CLIENT_REQUIREMENTS = ['arrr', 'aiohttp']
|
|
198
197
|
|
|
199
|
-
|
|
198
|
+
Must be placed in the root of the ``app/`` directory, i.e. the app directory must be the immediate parent of __settings__.py.
|
|
200
199
|
|
|
201
200
|
A __settings__.py file is not required, and an app without a __settings__.py file will be treated the same as an app whose __settings__.py is empty.
|
|
202
201
|
|
|
@@ -205,16 +204,36 @@ A __settings__.py file can have any of the following settings:
|
|
|
205
204
|
.. data:: CLIENT_REQUIREMENTS
|
|
206
205
|
:type: list[str]
|
|
207
206
|
:value: []
|
|
207
|
+
|
|
208
|
+
The Python libraries that Blu should install in the client environment.
|
|
208
209
|
|
|
209
210
|
.. code-block:: python
|
|
210
211
|
|
|
211
|
-
CLIENT_REQUIREMENTS = ['
|
|
212
|
+
CLIENT_REQUIREMENTS = ['abc', 'io']
|
|
213
|
+
|
|
214
|
+
If using the default Python interpreter, ``CLIENT_REQUIREMENTS`` can include any packages from the `micropython-lib repository <https://github.com/micropython/micropython-lib>`_, under the ``python-stdlib/``, ``python-ecosys/``, ``micropython/``, or ``unix-ffi/`` directories.
|
|
215
|
+
|
|
216
|
+
.. code-block:: python
|
|
217
|
+
|
|
218
|
+
CLIENT_REQUIREMENTS = ['bluetooth', 'io']
|
|
219
|
+
|
|
220
|
+
If :doc:`opting in to Pyodide </appendices/choosing-an-interpreter>`, ``CLIENT_REQUIREMENTS`` can include any values that can be passed in as requirements to Pyodide's `micropip.install() <https://micropip.pyodide.org/en/stable/project/api.html#micropip.install>`_ function.
|
|
221
|
+
|
|
222
|
+
.. code-block:: python
|
|
223
|
+
|
|
224
|
+
CLIENT_REQUIREMENTS = ['arrr', 'emoji']
|
|
225
|
+
|
|
226
|
+
.. data:: INTERPRETER
|
|
227
|
+
:type: typing.Literal['micropython', 'pyodide']
|
|
228
|
+
:value: 'micropython'
|
|
212
229
|
|
|
213
|
-
The Python
|
|
230
|
+
The Python interpreter to use for client-side code.
|
|
214
231
|
|
|
215
232
|
.. code-block:: python
|
|
216
233
|
|
|
217
|
-
|
|
234
|
+
INTERPRETER = 'pyodide'
|
|
235
|
+
|
|
236
|
+
See :doc:`/appendices/choosing-an-interpreter` for more details.
|
|
218
237
|
|
|
219
238
|
|
|
220
239
|
.. _file-conventions/files/what-does-triple-star-url-mean:
|
|
@@ -251,16 +270,16 @@ You can capture route parameters from dynamic route segments by passing them in
|
|
|
251
270
|
Capturing query parameters
|
|
252
271
|
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
253
272
|
|
|
254
|
-
Any arguments specified after
|
|
273
|
+
Any arguments specified after ``*`` in your call signature will capture query parameters instead of route parameters:
|
|
255
274
|
|
|
256
275
|
.. code-block:: python
|
|
257
276
|
:caption: app/_id_/__index__.py
|
|
258
277
|
|
|
259
278
|
from blu.html import p
|
|
260
279
|
|
|
261
|
-
def __page__(id,
|
|
280
|
+
def __page__(id, *, foo):
|
|
262
281
|
return (
|
|
263
|
-
p['ID:
|
|
282
|
+
p['ID:', id],
|
|
264
283
|
p['foo:', foo],
|
|
265
284
|
)
|
|
266
285
|
|
|
@@ -271,7 +290,7 @@ Any arguments specified after ``/`` in your call signature will capture query pa
|
|
|
271
290
|
<p>foo: 3</p>
|
|
272
291
|
|
|
273
292
|
|
|
274
|
-
|
|
293
|
+
You can capture query parameters without route parameters:
|
|
275
294
|
|
|
276
295
|
.. code-block:: python
|
|
277
296
|
:caption: app/greet_me/__index__.py
|
|
@@ -279,7 +298,7 @@ Python doesn't allow a ``/`` at the beginning of the call signature, so use ``_`
|
|
|
279
298
|
from blu.html import p
|
|
280
299
|
|
|
281
300
|
|
|
282
|
-
def __page__(
|
|
301
|
+
def __page__(*, my_name):
|
|
283
302
|
return p['Hello ', my_name, '!']
|
|
284
303
|
|
|
285
304
|
.. code-block:: html
|
|
@@ -295,7 +314,7 @@ You can set default values for query parameters:
|
|
|
295
314
|
from blu.html import p
|
|
296
315
|
|
|
297
316
|
|
|
298
|
-
def __page__(
|
|
317
|
+
def __page__(*, my_name='World'):
|
|
299
318
|
return p['Hello ', my_name, '!']
|
|
300
319
|
|
|
301
320
|
.. code-block:: html
|
|
@@ -311,7 +330,57 @@ You can also use ``**kwargs`` for query parameters:
|
|
|
311
330
|
from blu.html import p
|
|
312
331
|
|
|
313
332
|
|
|
314
|
-
def __page__(
|
|
333
|
+
def __page__(**kwargs):
|
|
334
|
+
greeting = kwargs.get('greeting', 'Hello')
|
|
335
|
+
return p[greeting, '!']
|
|
336
|
+
|
|
337
|
+
.. code-block:: html
|
|
338
|
+
:caption: GET /greet_me?greeting=Hi
|
|
339
|
+
|
|
340
|
+
<p>Hi!</p>
|
|
341
|
+
|
|
342
|
+
.. note::
|
|
343
|
+
|
|
344
|
+
If you capture query parameters using ``**kwargs`` while also capturing route paramaters, use ``/`` to avoid name collisions:
|
|
345
|
+
|
|
346
|
+
.. code-block:: python
|
|
347
|
+
:caption: app/show_params/__index__.py
|
|
348
|
+
|
|
349
|
+
from blu.html import p
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
def __page__(x, /, **kwargs):
|
|
353
|
+
return p[
|
|
354
|
+
div['x: ', x],
|
|
355
|
+
div['**kwargs:'],
|
|
356
|
+
ul[
|
|
357
|
+
li[f'{k}: ', v] for k, v in **kwargs
|
|
358
|
+
],
|
|
359
|
+
]
|
|
360
|
+
|
|
361
|
+
.. code-block:: html
|
|
362
|
+
:caption: GET /show_params/A?x=1&y=2&z=3
|
|
363
|
+
|
|
364
|
+
<p>
|
|
365
|
+
<div>x: A</div>
|
|
366
|
+
<div>**kwargs:</div>
|
|
367
|
+
<ul>
|
|
368
|
+
<li>x: 1</li>
|
|
369
|
+
<li>y: 2</li>
|
|
370
|
+
<li>z: 3</li>
|
|
371
|
+
</ul>
|
|
372
|
+
</p>
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
This can also be paired with non-``**kwarg`` query parameters:
|
|
376
|
+
|
|
377
|
+
.. code-block:: python
|
|
378
|
+
:caption: app/greet_me/__index__.py
|
|
379
|
+
|
|
380
|
+
from blu.html import p
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
def __page__(*, my_name, **kwargs):
|
|
315
384
|
greeting = kwargs.get('greeting', 'Hello')
|
|
316
385
|
return p[greeting, ' ', my_name, '!']
|
|
317
386
|
|
|
@@ -339,18 +408,18 @@ Since a call to a ``__page__`` handler in a ``__default__.py`` file usually resu
|
|
|
339
408
|
|
|
340
409
|
<p>Remaining path: bar/baz</p>
|
|
341
410
|
|
|
342
|
-
This can be used alongside route parameters and query parameters. In this case, it should come before the
|
|
411
|
+
This can be used alongside route parameters and query parameters. In this case, it should come before the ``*``:
|
|
343
412
|
|
|
344
413
|
.. code-block:: python
|
|
345
414
|
:caption: app/_id_/__default__.py
|
|
346
415
|
|
|
347
416
|
from blu.html import p
|
|
348
417
|
|
|
349
|
-
def __page__(id, path__,
|
|
418
|
+
def __page__(id, path__, *, baz):
|
|
350
419
|
return (
|
|
351
420
|
p['ID: ', id],
|
|
352
|
-
p['Remaining path:',
|
|
353
|
-
p['baz:', baz],
|
|
421
|
+
p['Remaining path: ', path__],
|
|
422
|
+
p['baz: ', baz],
|
|
354
423
|
)
|
|
355
424
|
|
|
356
425
|
.. code-block:: html
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
``js`` (client-only)
|
|
2
|
+
====================
|
|
3
|
+
|
|
4
|
+
The JavaScript global scope is available in the client-side Python environment through the ``js`` module:
|
|
5
|
+
|
|
6
|
+
.. code-block:: python
|
|
7
|
+
|
|
8
|
+
from blu import is_client
|
|
9
|
+
|
|
10
|
+
__client__ = True
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
if is_client:
|
|
14
|
+
from js import Promise, addEventListener, alert, document
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
.. note::
|
|
18
|
+
|
|
19
|
+
``js`` can only be imported in a client context.
|
|
20
|
+
|
|
21
|
+
.. code-block:: python
|
|
22
|
+
|
|
23
|
+
from blu import is_client
|
|
24
|
+
|
|
25
|
+
# Wrong!
|
|
26
|
+
from js import document
|
|
27
|
+
|
|
28
|
+
# Right.
|
|
29
|
+
if is_client:
|
|
30
|
+
from js import document
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
By default, Blu runs Python on the client using the MicroPython interpreter. You can view MicroPython's documentation on `in-browser type conversions <https://github.com/micropython/micropython/blob/master/ports/webassembly/README.md#proxying>`_ to learn how JavaScript types are converted into Python.
|
|
34
|
+
|
|
35
|
+
If you :doc:`opt in to using Pyodide </appendices/choosing-an-interpreter>` as your client-side Python interpreter, you can learn about Pyodide's type conversions `here <https://pyodide.org/en/stable/usage/type-conversions.html>`_.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
.. _pyscript:
|
|
2
|
+
|
|
3
|
+
``pyodide`` (opt-in)
|
|
4
|
+
====================
|
|
5
|
+
|
|
6
|
+
By default, Blu uses MicroPython as its client-side Python interpreter. However, you can also :doc:`opt in to using Pyodide </appendices/choosing-an-interpreter>` as your Python interpreter.
|
|
7
|
+
|
|
8
|
+
Pyodide provides an additional client-side package called ``pyodide``, which provides utilities for using Python in the browser.
|
|
9
|
+
|
|
10
|
+
.. code-block:: python
|
|
11
|
+
|
|
12
|
+
from blu import is_client
|
|
13
|
+
|
|
14
|
+
if is_client:
|
|
15
|
+
from pyodide.http import pyfetch
|
|
16
|
+
|
|
17
|
+
response = await pyfetch('https://www.example.com/api/v2/data')
|
|
18
|
+
print(await response.json())
|
|
19
|
+
|
|
20
|
+
.. note::
|
|
21
|
+
|
|
22
|
+
The ``pyodide`` package can only be imported in a client context.
|
|
23
|
+
|
|
24
|
+
.. code-block:: python
|
|
25
|
+
|
|
26
|
+
from blu import is_client
|
|
27
|
+
|
|
28
|
+
# Wrong!
|
|
29
|
+
from pyodide.http import pyfetch
|
|
30
|
+
|
|
31
|
+
# Right.
|
|
32
|
+
if is_client:
|
|
33
|
+
from pyodide.http import pyfetch
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
For more information on the ``pyodide`` package, see the package's official `API reference <https://pyodide.org/en/stable/usage/api/python-api.html>`_.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
.. _choosing-an-interpreter:
|
|
2
|
+
|
|
3
|
+
Choosing an Interpreter
|
|
4
|
+
=======================
|
|
5
|
+
|
|
6
|
+
The two most popular in-browser Python interpreters are Pyodide and MicroPython. Blu supports both, but uses MicroPython by default. To use Pyodide, set the interpreter in ``__settings__.py``:
|
|
7
|
+
|
|
8
|
+
.. code-block:: python
|
|
9
|
+
:caption: app/__settings__.py
|
|
10
|
+
|
|
11
|
+
INTERPRETER = 'pyodide'
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
Pyodide is CPython compiled to WebAssembly and has almost all the features available in other CPython distributions. MicroPython is a slim partial implementation of Python mainly used in microcontrollers. The main trade-offs are shown below:
|
|
15
|
+
|
|
16
|
+
.. list-table::
|
|
17
|
+
:header-rows: 1
|
|
18
|
+
|
|
19
|
+
* - Pyodide
|
|
20
|
+
- MicroPython
|
|
21
|
+
* - Implements almost all features of the Python language.
|
|
22
|
+
- Implements Python 3.10, with a few additional features from later versions.
|
|
23
|
+
* - Includes almost the entire Python standard library.
|
|
24
|
+
- Includes a small subset of the Python standard library, with some standard library packages available to be installed.
|
|
25
|
+
* - Provides Python APIs for interacting with the browser environment, as well as access to the JavaScript global scope.
|
|
26
|
+
- Only provides access to the JavaScript global scope.
|
|
27
|
+
* - Can have slow initial loads.
|
|
28
|
+
- Initial page load is almost instant.
|
|
@@ -10,13 +10,15 @@ Setup
|
|
|
10
10
|
|
|
11
11
|
3. Ensure `uv <https://docs.astral.sh/uv/>`_ is installed.
|
|
12
12
|
|
|
13
|
+
|
|
14
|
+
|
|
13
15
|
4. Run tests with ``uv run pytest``. If the tests pass, you have successfully set up your development environment and are ready to make a change to the codebase.
|
|
14
16
|
|
|
15
17
|
|
|
16
18
|
Making Changes
|
|
17
19
|
--------------
|
|
18
20
|
|
|
19
|
-
1. Update the :ref:`API Reference` (and :ref:`User Guide`, if appropriate) to reflect intended changes.
|
|
21
|
+
1. Update the :ref:`api-reference/index:API Reference` (and :ref:`user-guide/index:User Guide`, if appropriate) to reflect intended changes.
|
|
20
22
|
|
|
21
23
|
2. Write tests or update existing ones to test the feature or bug fix you are implementing.
|
|
22
24
|
|
|
@@ -29,4 +31,4 @@ Making Changes
|
|
|
29
31
|
Make a Pull Request Early
|
|
30
32
|
-------------------------
|
|
31
33
|
|
|
32
|
-
You don't have to wait until your changes are ready to merge to make a pull request. In fact, making a pull request early allows you to get early feedback, preventing you from doing significant work that is later rejected. For example, a pull request with
|
|
34
|
+
You don't have to wait until your changes are ready to merge to make a pull request. In fact, making a pull request early allows you to get early feedback, preventing you from doing significant work that is later rejected. For example, a pull request with only proposed documentation changes allows revisions to be made before anything is implemented, and a pull request with initial work allows revisions to be made to the implementation stategy before more work has been put into the implementation.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Quickstart
|
|
2
2
|
==========
|
|
3
3
|
|
|
4
|
-
If you haven't already, :ref:`install Blu <install>`.
|
|
4
|
+
If you haven't already, :ref:`install Blu <install:Install>`.
|
|
5
5
|
|
|
6
6
|
Next, create a directory called ``app``. Inside this directory, create a file called ``__index__.py`` with the following content:
|
|
7
7
|
|
|
@@ -39,4 +39,4 @@ This will start up the app and output a url where you can access it (``http://12
|
|
|
39
39
|
|
|
40
40
|
If it works, you've created a simple web app using Blu.
|
|
41
41
|
|
|
42
|
-
To learn how make more complex pages in Blu, see :ref:`Creating Pages`.
|
|
42
|
+
To learn how make more complex pages in Blu, see :ref:`user-guide/creating-pages:Creating Pages`.
|
|
@@ -224,7 +224,7 @@ What's going on here is:
|
|
|
224
224
|
7. React sets the state value to 1, and then calls *MyClientElement*'s render function again. This time, the current value is 1, so *click_count* is 1, so the button will say "Click Count: 1".
|
|
225
225
|
8. If the user clicks the button again, the current value will again be incremented, and the render function will be called again, resulting in a button that says "Click Count: 2".
|
|
226
226
|
|
|
227
|
-
.. note:: :func:`use_state <blu.use_state>` is a special type of function used in React called a *hook*. There are specific rules you have to follow when using hooks. See :ref:`Hooks` for more details.
|
|
227
|
+
.. note:: :func:`use_state <blu.use_state>` is a special type of function used in React called a *hook*. There are specific rules you have to follow when using hooks. See :ref:`user-guide/client-side-rendering:Hooks` for more details.
|
|
228
228
|
|
|
229
229
|
|
|
230
230
|
Directly Manipulating Rendered Elements
|
|
@@ -272,7 +272,7 @@ What's happening here is:
|
|
|
272
272
|
1. Gets the current value of *input_ref* using ``[:]`` (remember that the current value is the rendered input element).
|
|
273
273
|
2. Calls the *focus()* method on that value. Because the current value is a rendered HTML input element, calling its *focus()* method causes the input element to receive the browser's focus.
|
|
274
274
|
|
|
275
|
-
.. note:: :func:`use_ref <blu.use_ref>` is a special type of function used in React called a *hook*. There are specific rules you have to follow when using hooks. See :ref:`Hooks` for more details.
|
|
275
|
+
.. note:: :func:`use_ref <blu.use_ref>` is a special type of function used in React called a *hook*. There are specific rules you have to follow when using hooks. See :ref:`user-guide/client-side-rendering:Hooks` for more details.
|
|
276
276
|
|
|
277
277
|
|
|
278
278
|
Performing an Action Immediately After Rendering
|
|
@@ -316,7 +316,7 @@ What's happening here:
|
|
|
316
316
|
7. This causes an alert modal to pop up in front of the page with the provided message.
|
|
317
317
|
8. The user can then dismiss the alert modal.
|
|
318
318
|
|
|
319
|
-
.. note:: :func:`use_effect <blu.use_effect>` is a special type of function used in React called a *hook*. There are specific rules you have to follow when using hooks. See :ref:`Hooks` for more details.
|
|
319
|
+
.. note:: :func:`use_effect <blu.use_effect>` is a special type of function used in React called a *hook*. There are specific rules you have to follow when using hooks. See :ref:`user-guide/client-side-rendering:Hooks` for more details.
|
|
320
320
|
|
|
321
321
|
.. note::
|
|
322
322
|
|
|
@@ -355,7 +355,7 @@ What's happening here:
|
|
|
355
355
|
Accessing Server-Side Resources from the Client
|
|
356
356
|
-----------------------------------------------
|
|
357
357
|
|
|
358
|
-
Sometimes you'll need to access server-side resources after a page has loaded, usually in response to user input. You can do using the :func:`@blu.server` decorator, which exposes a server-side function to be called client-side.
|
|
358
|
+
Sometimes you'll need to access server-side resources after a page has loaded, usually in response to user input. You can do so using the :func:`@blu.server` decorator, which exposes a server-side function to be called client-side.
|
|
359
359
|
|
|
360
360
|
.. code-block:: python
|
|
361
361
|
:caption: app/hello_module.py
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Creating Pages
|
|
4
4
|
==============
|
|
5
5
|
|
|
6
|
-
The :ref:`Quickstart` guide shows how to make a simple page using Blu.
|
|
6
|
+
The :ref:`quickstart:Quickstart` guide shows how to make a simple page using Blu.
|
|
7
7
|
|
|
8
8
|
This section goes into greater depth on how to generate user interfaces using Blu.
|
|
9
9
|
|
|
@@ -11,7 +11,7 @@ This section goes into greater depth on how to generate user interfaces using Bl
|
|
|
11
11
|
HTML Elements
|
|
12
12
|
-------------
|
|
13
13
|
|
|
14
|
-
The :ref:`Quickstart` guide shows how to make a simple page with html, head, and body elements:
|
|
14
|
+
The :ref:`quickstart:Quickstart` guide shows how to make a simple page with html, head, and body elements:
|
|
15
15
|
|
|
16
16
|
.. code-block:: python
|
|
17
17
|
|
|
@@ -140,7 +140,7 @@ You can set the HTML attributes of an element by calling it as a function:
|
|
|
140
140
|
|
|
141
141
|
.. note::
|
|
142
142
|
|
|
143
|
-
Event-handling attributes like "onClick" are only supported in client-side rendering (see :ref:`Client-Side Rendering` for more details).
|
|
143
|
+
Event-handling attributes like "onClick" are only supported in client-side rendering (see :ref:`user-guide/client-side-rendering:Client-Side Rendering` for more details).
|
|
144
144
|
|
|
145
145
|
.. code-block:: python
|
|
146
146
|
|
|
@@ -5,7 +5,7 @@ Blu is an ASGI framework, meaning it doesn't include tools for running a product
|
|
|
5
5
|
|
|
6
6
|
If you're familiar with ASGI frameworks, you may be wondering, "Where is the ASGI app?" The app you'll use to deploy is :data:`blu.app`.
|
|
7
7
|
|
|
8
|
-
For example, to deploy your app using `Uvicorn <uvicorn.
|
|
8
|
+
For example, to deploy your app using `Uvicorn <https://uvicorn.dev>`_, run the following from your ``app/`` directory's parent directory (not the ``app/`` directory itself):
|
|
9
9
|
|
|
10
10
|
.. code-block:: console
|
|
11
11
|
|