Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
fb03ab6
bump python>=3.10 then run `hatch fmt`
Archmonger Dec 9, 2025
b1b4985
reorganize changelog
Archmonger Dec 9, 2025
3a8a0b2
remove `ComponentType`, replace with `Component`
Archmonger Dec 9, 2025
3780568
Better error msg if optional dependencies are missing
Archmonger Dec 9, 2025
8d89231
Remove `ContextProviderType`, replace with `ContextProvider`
Archmonger Dec 9, 2025
fa7d60e
Remove unsafe orjson dependency
Archmonger Dec 9, 2025
11e6a9a
Support auto-naming for ReactJS component imports
Archmonger Dec 9, 2025
743b955
Make `ContextProvider` inherit from `Component`
Archmonger Dec 9, 2025
058e3c6
fix pyscript tests
Archmonger Dec 9, 2025
30a8bf6
`EventHandlerType` -> `BaseEventHandler`
Archmonger Dec 9, 2025
c81fec5
`LayoutType` -> `BaseLayout`
Archmonger Dec 9, 2025
747cab8
use remote `event-to-object` copy in `reactpy/client`
Archmonger Dec 9, 2025
daee110
Remove `pip` dependency
Archmonger Dec 10, 2025
70e0578
bump version
Archmonger Dec 10, 2025
169b238
bump reactpy client
Archmonger Dec 10, 2025
03144ac
add changelog
Archmonger Dec 10, 2025
3a96533
Set minimum python version to 3.11
Archmonger Dec 10, 2025
f473b54
fix python 3.14 warnings
Archmonger Dec 10, 2025
f8e6488
fix python 3.14 tests
Archmonger Dec 10, 2025
e218929
speed-up event parsing
Archmonger Dec 10, 2025
570096b
Allow generic ReactJS component bindings (fix #1001)
Archmonger Dec 10, 2025
830029d
another fix for python 3.14 tests
Archmonger Dec 10, 2025
76571cc
fix coverage
Archmonger Dec 10, 2025
c43a641
Add new changelog entry
Archmonger Dec 10, 2025
cd55de6
Refactor layout rendering (fix #624)
Archmonger Dec 10, 2025
3bd6c84
Fix error for bad use effect usage
Archmonger Dec 10, 2025
71f6c4e
``REACTPY_ASYNC_RENDERING` can now de-duplicate and cascade renders (…
Archmonger Dec 10, 2025
58c2ac6
Default async rendering to True
Archmonger Dec 10, 2025
7ef96a3
fix coverage
Archmonger Dec 10, 2025
a7738a3
another coverage fix
Archmonger Dec 10, 2025
afed1c2
update AI instructions to use serena
Archmonger Dec 10, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
271 changes: 153 additions & 118 deletions .github/copilot-instructions.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
job-name: "python-{0} {1}"
run-cmd: "hatch test"
runs-on: '["ubuntu-latest", "macos-latest", "windows-latest"]'
python-version: '["3.10", "3.11", "3.12", "3.13"]'
python-version: '["3.11", "3.12", "3.13", "3.14"]'
test-documentation:
# Temporarily disabled while we transition from Sphinx to MkDocs
# https://github.com/reactive-python/reactpy/pull/1052
Expand Down
3 changes: 2 additions & 1 deletion .prettierrc
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"proseWrap": "never",
"trailingComma": "all"
"trailingComma": "all",
"endOfLine": "auto"
}
1 change: 1 addition & 0 deletions .serena/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/cache
8 changes: 8 additions & 0 deletions .serena/memories/code_style.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Code Style & Conventions

- **Formatting**: Enforced by `hatch fmt`.
- **Type Hints**: Required, checked by `hatch run python:type_check`.
- **JS Linting**: Enforced by `hatch run javascript:check`.
- **Tests**: All tests must pass. Failures not allowed.
- **Documentation**: Must be updated with code changes.
- **Changelog**: Required for significant changes.
12 changes: 12 additions & 0 deletions .serena/memories/development_workflow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Development Workflow

1. **Bootstrap**: Install Python 3.9+, Hatch, Bun.
2. **Changes**: Modify code.
3. **Format**: `hatch fmt`.
4. **Type Check**: `hatch run python:type_check`.
5. **JS Check**: `hatch run javascript:check` (if JS changed).
6. **Test**: `hatch test`.
7. **Validate**: Manual component/server tests.
8. **Build JS**: `hatch run javascript:build` (if JS changed).
9. **Docs**: Update if Python source changed.
10. **Changelog**: Add entry in `docs/source/about/changelog.rst`.
16 changes: 16 additions & 0 deletions .serena/memories/project_overview.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# ReactPy Overview

## Purpose
ReactPy builds UIs in Python without JS, using React-like components and a Python-to-JS bridge.

## Tech Stack
- **Python**: 3.9+
- **Build**: Hatch
- **JS Runtime**: Bun
- **Deps**: fastjsonschema, requests, lxml, anyio

## Structure
- `src/reactpy/`: Python source (core, web, executors).
- `src/js/`: JS packages (client, app).
- `tests/`: Test suite.
- `docs/`: Documentation.
17 changes: 17 additions & 0 deletions .serena/memories/suggested_commands.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Suggested Commands (Hatch)

## Python
- **Test**: `hatch test` (All must pass)
- **Coverage**: `hatch test --cover`
- **Format**: `hatch fmt`
- **Check Format**: `hatch fmt --check`
- **Type Check**: `hatch run python:type_check`
- **Build**: `hatch build --clean`

## JavaScript
- **Build**: `hatch run javascript:build` (Rebuild after JS changes)
- **Check**: `hatch run javascript:check`
- **Fix**: `hatch run javascript:fix`

## Shell
- **Dev Shell**: `hatch shell`
84 changes: 84 additions & 0 deletions .serena/project.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# list of languages for which language servers are started; choose from:
# al bash clojure cpp csharp csharp_omnisharp
# dart elixir elm erlang fortran go
# haskell java julia kotlin lua markdown
# nix perl php python python_jedi r
# rego ruby ruby_solargraph rust scala swift
# terraform typescript typescript_vts yaml zig
# Note:
# - For C, use cpp
# - For JavaScript, use typescript
# Special requirements:
# - csharp: Requires the presence of a .sln file in the project folder.
# When using multiple languages, the first language server that supports a given file will be used for that file.
# The first language is the default language and the respective language server will be used as a fallback.
# Note that when using the JetBrains backend, language servers are not used and this list is correspondingly ignored.
languages:
- python

# the encoding used by text files in the project
# For a list of possible encodings, see https://docs.python.org/3.11/library/codecs.html#standard-encodings
encoding: "utf-8"

# whether to use the project's gitignore file to ignore files
# Added on 2025-04-07
ignore_all_files_in_gitignore: true

# list of additional paths to ignore
# same syntax as gitignore, so you can use * and **
# Was previously called `ignored_dirs`, please update your config if you are using that.
# Added (renamed) on 2025-04-07
ignored_paths: []

# whether the project is in read-only mode
# If set to true, all editing tools will be disabled and attempts to use them will result in an error
# Added on 2025-04-18
read_only: false

# list of tool names to exclude. We recommend not excluding any tools, see the readme for more details.
# Below is the complete list of tools for convenience.
# To make sure you have the latest list of tools, and to view their descriptions,
# execute `uv run scripts/print_tool_overview.py`.
#
# * `activate_project`: Activates a project by name.
# * `check_onboarding_performed`: Checks whether project onboarding was already performed.
# * `create_text_file`: Creates/overwrites a file in the project directory.
# * `delete_lines`: Deletes a range of lines within a file.
# * `delete_memory`: Deletes a memory from Serena's project-specific memory store.
# * `execute_shell_command`: Executes a shell command.
# * `find_referencing_code_snippets`: Finds code snippets in which the symbol at the given location is referenced.
# * `find_referencing_symbols`: Finds symbols that reference the symbol at the given location (optionally filtered by type).
# * `find_symbol`: Performs a global (or local) search for symbols with/containing a given name/substring (optionally filtered by type).
# * `get_current_config`: Prints the current configuration of the agent, including the active and available projects, tools, contexts, and modes.
# * `get_symbols_overview`: Gets an overview of the top-level symbols defined in a given file.
# * `initial_instructions`: Gets the initial instructions for the current project.
# Should only be used in settings where the system prompt cannot be set,
# e.g. in clients you have no control over, like Claude Desktop.
# * `insert_after_symbol`: Inserts content after the end of the definition of a given symbol.
# * `insert_at_line`: Inserts content at a given line in a file.
# * `insert_before_symbol`: Inserts content before the beginning of the definition of a given symbol.
# * `list_dir`: Lists files and directories in the given directory (optionally with recursion).
# * `list_memories`: Lists memories in Serena's project-specific memory store.
# * `onboarding`: Performs onboarding (identifying the project structure and essential tasks, e.g. for testing or building).
# * `prepare_for_new_conversation`: Provides instructions for preparing for a new conversation (in order to continue with the necessary context).
# * `read_file`: Reads a file within the project directory.
# * `read_memory`: Reads the memory with the given name from Serena's project-specific memory store.
# * `remove_project`: Removes a project from the Serena configuration.
# * `replace_lines`: Replaces a range of lines within a file with new content.
# * `replace_symbol_body`: Replaces the full definition of a symbol.
# * `restart_language_server`: Restarts the language server, may be necessary when edits not through Serena happen.
# * `search_for_pattern`: Performs a search for a pattern in the project.
# * `summarize_changes`: Provides instructions for summarizing the changes made to the codebase.
# * `switch_modes`: Activates modes by providing a list of their names
# * `think_about_collected_information`: Thinking tool for pondering the completeness of collected information.
# * `think_about_task_adherence`: Thinking tool for determining whether the agent is still on track with the current task.
# * `think_about_whether_you_are_done`: Thinking tool for determining whether the task is truly completed.
# * `write_memory`: Writes a named memory (for future reference) to Serena's project-specific memory store.
excluded_tools: []

# initial prompt for the project. It will always be given to the LLM upon activating the project
# (contrary to the memories, which are loaded on demand).
initial_prompt: ""

project_name: "reactpy"
included_optional_tools: []
51 changes: 29 additions & 22 deletions docs/source/about/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,44 +17,49 @@ Unreleased

**Added**

- :pull:`1113` - Added support for Python 3.12, 3.13, and 3.14.
- :pull:`1281` - Added type hints to ``reactpy.html`` attributes.
- :pull:`1285` - Added support for nested components in web modules
- :pull:`1289` - Added support for inline JavaScript as event handlers or other attributes that expect a callable via ``reactpy.types.InlineJavaScript``
- :pull:`1308` - Event functions can now call ``event.preventDefault()`` and ``event.stopPropagation()`` methods directly on the event data object, rather than using the ``@event`` decorator.
- :pull:`1308` - Event data now supports accessing properties via dot notation (ex. ``event.target.value``).
- :pull:`1308` - Added ``reactpy.types.Event`` to provide type hints for the standard ``data`` function argument (for example ``def on_click(event: Event): ...``).
- :pull:`1113` - Added ``asgi`` and ``jinja`` installation extras (for example ``pip install reactpy[asgi, jinja]``).
- :pull:`1267` - Added ``shutdown_timeout`` parameter to the ``reactpy.use_async_effect`` hook.
- :pull:`1113` - Added ``reactpy.executors.asgi.ReactPy`` that can be used to run ReactPy in standalone mode via ASGI.
- :pull:`1269` - Added ``reactpy.executors.asgi.ReactPyCsr`` that can be used to run ReactPy in standalone mode via ASGI, but rendered entirely client-sided.
- :pull:`1113` - Added ``reactpy.executors.asgi.ReactPyMiddleware`` that can be used to utilize ReactPy within any ASGI compatible framework.
- :pull:`1269` - Added ``reactpy.templatetags.ReactPyJinja`` that can be used alongside ``ReactPyMiddleware`` to embed several ReactPy components into your existing application. This includes the following template tags: ``{% component %}``, ``{% pyscript_component %}``, and ``{% pyscript_setup %}``.
- :pull:`1269` - Added ``reactpy.pyscript_component`` that can be used to embed ReactPy components into your existing application.
- :pull:`1113` - Added ``asgi`` and ``jinja`` installation extras (for example ``pip install reactpy[asgi, jinja]``).
- :pull:`1113` - Added support for Python 3.12 and 3.13.
- :pull:`1264` - Added ``reactpy.use_async_effect`` hook.
- :pull:`1267` - Added ``shutdown_timeout`` parameter to the ``reactpy.use_async_effect`` hook.
- :pull:`1281` - ``reactpy.html`` will now automatically flatten lists recursively (ex. ``reactpy.html(["child1", ["child2"]])``)
- :pull:`1281` - Added ``reactpy.Vdom`` primitive interface for creating VDOM dictionaries.
- :pull:`1281` - Added type hints to ``reactpy.html`` attributes.
- :pull:`1285` - Added support for nested components in web modules
- :pull:`1289` - Added support for inline JavaScript as event handlers or other attributes that expect a callable via ``reactpy.types.InlineJavaScript``
- :pull:`1307` - Added ``reactpy.web.reactjs_component_from_file`` to import ReactJS components from a file.
- :pull:`1307` - Added ``reactpy.web.reactjs_component_from_url`` to import ReactJS components from a URL.
- :pull:`1307` - Added ``reactpy.web.reactjs_component_from_string`` to import ReactJS components from a string.
- :pull:`1308` - Event functions can now call ``event.preventDefault()`` and ``event.stopPropagation()`` methods directly on the event data object, rather than using the ``@event`` decorator.
- :pull:`1308` - Event data now supports accessing properties via dot notation (ex. ``event.target.value``).

**Changed**

- :pull:`1251` - Substitute client-side usage of ``react`` with ``preact``.
- :pull:`1239` - Script elements no longer support behaving like effects. They now strictly behave like plain HTML script elements.
- :pull:`1239` - Script elements no longer support behaving like effects. They now strictly behave like plain HTML scripts.
- :pull:`1255` - The ``reactpy.html`` module has been modified to allow for auto-creation of any HTML nodes. For example, you can create a ``<data-table>`` element by calling ``html.data_table()``.
- :pull:`1256` - Change ``set_state`` comparison method to check equality with ``==`` more consistently.
- :pull:`1257` - Add support for rendering ``@component`` children within ``vdom_to_html``.
- :pull:`1113` - Renamed the ``use_location`` hook's ``search`` attribute to ``query_string``.
- :pull:`1113` - Renamed the ``use_location`` hook's ``pathname`` attribute to ``path``.
- :pull:`1113` - Renamed ``reactpy.config.REACTPY_DEBUG_MODE`` to ``reactpy.config.REACTPY_DEBUG``.
- :pull:`1113` - ``@reactpy/client`` now exports ``React`` and ``ReactDOM``.
- :pull:`1263` - ReactPy no longer auto-converts ``snake_case`` props to ``camelCase``. It is now the responsibility of the user to ensure that props are in the correct format.
- :pull:`1196` - Rewrite the ``event-to-object`` package to be more robust at handling properties on events.
- :pull:`1312` - Custom JS components will now automatically assume you are using ReactJS in the absence of a ``bind`` function.
- :pull:`1312` - Refactor layout rendering logic to improve readability and maintainability.
- :pull:`1113` - ``@reactpy/client`` now exports ``React`` and ``ReactDOM``.
- :pull:`1281` - ``reactpy.html`` will now automatically flatten lists recursively (ex. ``reactpy.html(["child1", ["child2"]])``)
- :pull:`1278` - ``reactpy.utils.reactpy_to_string`` will now retain the user's original casing for ``data-*`` and ``aria-*`` attributes.
- :pull:`1278` - ``reactpy.utils.string_to_reactpy`` has been upgraded to handle more complex scenarios without causing ReactJS rendering errors.
- :pull:`1281` - ``reactpy.core.vdom._CustomVdomDictConstructor`` has been moved to ``reactpy.types.CustomVdomConstructor``.
- :pull:`1281` - ``reactpy.core.vdom._EllipsisRepr`` has been moved to ``reactpy.types.EllipsisRepr``.
- :pull:`1281` - ``reactpy.types.VdomDictConstructor`` has been renamed to ``reactpy.types.VdomConstructor``.
- :pull:`1196` - Rewrite the ``event-to-object`` package to be more robust at handling properties on events.
- :pull:`1312` - ``REACTPY_ASYNC_RENDERING`` can now de-duplicate and cascade renders where necessary.
- :pull:`1312` - ``REACTPY_ASYNC_RENDERING`` is now defaulted to ``True`` for up to 40x performance improvements.

**Deprecated**

Expand All @@ -63,10 +68,15 @@ Unreleased
-:pull:`1307` - ``reactpy.web.module_from_url`` is deprecated. Use ``reactpy.web.reactjs_component_from_url`` instead.
-:pull:`1307` - ``reactpy.web.module_from_string`` is deprecated. Use ``reactpy.web.reactjs_component_from_string`` instead.


**Removed**

- :pull:`1113` - Removed support for Python 3.9 and 3.10.
- :pull:`1255` - Removed the ability to import ``reactpy.html.*`` elements directly. You must now call ``html.*`` to access the elements.
- :pull:`1113` - Removed backend specific installation extras (such as ``pip install reactpy[starlette]``).
- :pull:`1264` - Removed support for async functions within ``reactpy.use_effect`` hook. Use ``reactpy.use_async_effect`` instead.
- :pull:`1113` - Removed deprecated function ``module_from_template``.
- :pull:`1311` - Removed deprecated exception type ``reactpy.core.serve.Stop``.
- :pull:`1311` - Removed deprecated component ``reactpy.widgets.hotswap``.
- :pull:`1255` - Removed ``reactpy.sample`` module.
- :pull:`1255` - Removed ``reactpy.svg`` module. Contents previously within ``reactpy.svg.*`` can now be accessed via ``html.svg.*``.
- :pull:`1255` - Removed ``reactpy.html._`` function. Use ``html.fragment`` instead.
Expand All @@ -75,24 +85,21 @@ Unreleased
- :pull:`1113` - Removed ``reactpy.core.types`` module. Use ``reactpy.types`` instead.
- :pull:`1278` - Removed ``reactpy.utils.html_to_vdom``. Use ``reactpy.utils.string_to_reactpy`` instead.
- :pull:`1278` - Removed ``reactpy.utils.vdom_to_html``. Use ``reactpy.utils.reactpy_to_string`` instead.
- :pull:`1113` - Removed backend specific installation extras (such as ``pip install reactpy[starlette]``).
- :pull:`1113` - Removed deprecated function ``module_from_template``.
- :pull:`1113` - Removed support for Python 3.9.
- :pull:`1264` - Removed support for async functions within ``reactpy.use_effect`` hook. Use ``reactpy.use_async_effect`` instead.
- :pull:`1281` - Removed ``reactpy.vdom``. Use ``reactpy.Vdom`` instead.
- :pull:`1281` - Removed ``reactpy.core.make_vdom_constructor``. Use ``reactpy.Vdom`` instead.
- :pull:`1281` - Removed ``reactpy.core.custom_vdom_constructor``. Use ``reactpy.Vdom`` instead.
- :pull:`1311` - Removed ``reactpy.core.serve.Stop`` type due to extended deprecation.
- :pull:`1311` - Removed ``reactpy.Layout`` top-level export. Use ``reactpy.core.layout.Layout`` instead.
- :pull:`1311` - Removed ``reactpy.widgets.hotswap`` due to extended deprecation.

- :pull:`1311` - Removed ``reactpy.Layout`` top-level re-export. Use ``reactpy.core.layout.Layout`` instead.
- :pull:`1312` - Removed ``reactpy.types.LayoutType``. Use ``reactpy.types.BaseLayout`` instead.
- :pull:`1312` - Removed ``reactpy.types.ContextProviderType``. Use ``reactpy.types.ContextProvider`` instead.
- :pull:`1312` - Removed ``reactpy.core.hooks._ContextProvider``. Use ``reactpy.types.ContextProvider`` instead.

**Fixed**

- :pull:`1239` - Fixed a bug where script elements would not render to the DOM as plain text.
- :pull:`1271` - Fixed a bug where the ``key`` property provided within server-side ReactPy code was failing to propagate to the front-end JavaScript components.
- :pull:`1254` - Fixed a bug where ``RuntimeError("Hook stack is in an invalid state")`` errors could be generated when using a webserver that reuses threads.


v1.1.0
------
:octicon:`milestone` *released on 2024-11-24*
Expand All @@ -102,7 +109,7 @@ v1.1.0
- :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:`1224` - Fixed needless unmounting of JavaScript components during each ReactPy render.
- :pull:`1126` - Fixed missing ``event["target"]["checked"]`` on checkbox inputs
- :pull:`1191` - Fixed missing static files on `sdist` Python distribution

Expand Down
23 changes: 17 additions & 6 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,32 @@ requires = ["hatchling", "hatch-build-scripts"]
name = "reactpy"
description = "It's React, but in Python."
readme = "README.md"
keywords = ["react", "javascript", "reactpy", "component"]
keywords = [
"react",
"reactjs",
"reactpy",
"components",
"asgi",
"wsgi",
"website",
"interactive",
"reactive",
"javascript",
"server",
]
license = "MIT"
authors = [
{ name = "Mark Bakhit", email = "archiethemonger@gmail.com" },
{ name = "Ryan Morshead", email = "ryan.morshead@gmail.com" },
]
requires-python = ">=3.9"
requires-python = ">=3.11"
classifiers = [
"Development Status :: 5 - Production/Stable",
"Programming Language :: Python",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
]
Expand All @@ -32,7 +44,6 @@ dependencies = [
"requests >=2",
"lxml >=4",
"anyio >=3",
"typing-extensions >=3.10",
]
dynamic = ["version"]
urls.Changelog = "https://reactpy.dev/docs/about/changelog.html"
Expand All @@ -41,7 +52,7 @@ urls.Source = "https://github.com/reactive-python/reactpy"

[project.optional-dependencies]
all = ["reactpy[asgi,jinja,testing]"]
asgi = ["asgiref", "asgi-tools", "servestatic", "orjson", "pip"]
asgi = ["asgiref", "asgi-tools", "servestatic", "orjson"]
jinja = ["jinja2-simple-tags", "jinja2 >=3"]
testing = ["playwright", "uvicorn[standard]"]

Expand Down Expand Up @@ -95,7 +106,7 @@ extra-dependencies = [
features = ["all"]

[[tool.hatch.envs.hatch-test.matrix]]
python = ["3.10", "3.11", "3.12", "3.13"]
python = ["3.11", "3.12", "3.13", "3.14"]

[tool.pytest.ini_options]
addopts = ["--strict-config", "--strict-markers"]
Expand Down
Binary file modified src/js/bun.lockb
Binary file not shown.
Loading
Loading