Skip to content

Commit 793bd57

Browse files
committed
Merge remote-tracking branch 'upstream/develop' into fix-corrupted-hook-state
2 parents e85723d + d5a897e commit 793bd57

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

75 files changed

+2179
-852
lines changed

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# --- Build Artifacts ---
2-
src/reactpy/static/*
2+
src/reactpy/static/index.js*
3+
src/reactpy/static/morphdom/
4+
src/reactpy/static/pyscript/
35

46
# --- Jupyter ---
57
*.ipynb_checkpoints

docs/source/about/changelog.rst

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,15 @@ Unreleased
1616
----------
1717

1818
**Added**
19-
- :pull:`1113` - Added ``reactpy.ReactPy`` that can be used to run ReactPy in standalone mode.
20-
- :pull:`1113` - Added ``reactpy.ReactPyMiddleware`` that can be used to run ReactPy with any ASGI compatible framework.
21-
- :pull:`1113` - Added ``reactpy.jinja.Component`` that can be used alongside ``ReactPyMiddleware`` to embed several ReactPy components into your existing application.
22-
- :pull:`1113` - Added ``standard``, ``uvicorn``, ``jinja`` installation extras (for example ``pip install reactpy[standard]``).
19+
- :pull:`1113` - Added ``reactpy.executors.asgi.ReactPy`` that can be used to run ReactPy in standalone mode via ASGI.
20+
- :pull:`1269` - Added ``reactpy.executors.asgi.ReactPyPyodide`` that can be used to run ReactPy in standalone mode via ASGI, but rendered entirely client-sided.
21+
- :pull:`1113` - Added ``reactpy.executors.asgi.ReactPyMiddleware`` that can be used to utilize ReactPy within any ASGI compatible framework.
22+
- :pull:`1113` :pull:`1269` - Added ``reactpy.templatetags.Jinja`` 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 %}``.
23+
- :pull:`1269` - Added ``reactpy.pyscript_component`` that can be used to embed ReactPy components into your existing application.
24+
- :pull:`1113` - Added ``uvicorn`` and ``jinja`` installation extras (for example ``pip install reactpy[jinja]``).
2325
- :pull:`1113` - Added support for Python 3.12 and 3.13.
26+
- :pull:`1264` - Added ``reactpy.use_async_effect`` hook.
27+
- :pull:`1267` - Added ``shutdown_timeout`` parameter to the ``reactpy.use_async_effect`` hook.
2428

2529
**Changed**
2630

@@ -32,6 +36,8 @@ Unreleased
3236
- :pull:`1113` - Renamed the ``use_location`` hook's ``search`` attribute to ``query_string``.
3337
- :pull:`1113` - Renamed the ``use_location`` hook's ``pathname`` attribute to ``path``.
3438
- :pull:`1113` - Renamed ``reactpy.config.REACTPY_DEBUG_MODE`` to ``reactpy.config.REACTPY_DEBUG``.
39+
- :pull:`1113` - ``@reactpy/client`` now exports ``React`` and ``ReactDOM``.
40+
- :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.
3541

3642
**Removed**
3743

@@ -45,6 +51,7 @@ Unreleased
4551
- :pull:`1113` - All backend related installation extras (such as ``pip install reactpy[starlette]``) have been removed.
4652
- :pull:`1113` - Removed deprecated function ``module_from_template``.
4753
- :pull:`1113` - Removed support for Python 3.9.
54+
- :pull:`1264` - Removed support for async functions within ``reactpy.use_effect`` hook. Use ``reactpy.use_async_effect`` instead.
4855

4956
**Fixed**
5057

docs/source/reference/_examples/simple_dashboard.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ def RandomWalkGraph(mu, sigma):
4949
interval = use_interval(0.5)
5050
data, set_data = reactpy.hooks.use_state([{"x": 0, "y": 0}] * 50)
5151

52-
@reactpy.hooks.use_effect
52+
@reactpy.hooks.use_async_effect
5353
async def animate():
5454
await interval
5555
last_data_point = data[-1]

docs/source/reference/_examples/snake_game.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ def on_direction_change(event):
9090

9191
interval = use_interval(0.5)
9292

93-
@reactpy.hooks.use_effect
93+
@reactpy.hooks.use_async_effect
9494
async def animate():
9595
if new_game_state is not None:
9696
await asyncio.sleep(1)

pyproject.toml

Lines changed: 32 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -13,37 +13,39 @@ readme = "README.md"
1313
keywords = ["react", "javascript", "reactpy", "component"]
1414
license = "MIT"
1515
authors = [
16-
{ name = "Ryan Morshead", email = "ryan.morshead@gmail.com" },
1716
{ name = "Mark Bakhit", email = "archiethemonger@gmail.com" },
17+
{ name = "Ryan Morshead", email = "ryan.morshead@gmail.com" },
1818
]
1919
requires-python = ">=3.9"
2020
classifiers = [
21-
"Development Status :: 4 - Beta",
21+
"Development Status :: 5 - Production/Stable",
2222
"Programming Language :: Python",
23-
"Programming Language :: Python :: 3.9",
2423
"Programming Language :: Python :: 3.10",
2524
"Programming Language :: Python :: 3.11",
25+
"Programming Language :: Python :: 3.12",
26+
"Programming Language :: Python :: 3.13",
2627
"Programming Language :: Python :: Implementation :: CPython",
2728
"Programming Language :: Python :: Implementation :: PyPy",
2829
]
2930
dependencies = [
30-
"exceptiongroup >=1.0",
31-
"typing-extensions >=3.10",
32-
"anyio >=3",
33-
"jsonpatch >=1.32",
3431
"fastjsonschema >=2.14.5",
3532
"requests >=2",
36-
"colorlog >=6",
37-
"asgiref >=3",
3833
"lxml >=4",
39-
"servestatic >=3.0.0",
40-
"orjson >=3",
34+
"anyio >=3",
35+
"typing-extensions >=3.10",
4136
]
4237
dynamic = ["version"]
4338
urls.Changelog = "https://reactpy.dev/docs/about/changelog.html"
4439
urls.Documentation = "https://reactpy.dev/"
4540
urls.Source = "https://github.com/reactive-python/reactpy"
4641

42+
[project.optional-dependencies]
43+
all = ["reactpy[asgi,jinja,uvicorn,testing]"]
44+
asgi = ["asgiref", "asgi-tools", "servestatic", "orjson", "pip"]
45+
jinja = ["jinja2-simple-tags", "jinja2 >=3"]
46+
uvicorn = ["uvicorn[standard]"]
47+
testing = ["playwright"]
48+
4749
[tool.hatch.version]
4850
path = "src/reactpy/__init__.py"
4951

@@ -60,6 +62,9 @@ license-files = { paths = ["LICENSE"] }
6062
[tool.hatch.envs.default]
6163
installer = "uv"
6264

65+
[project.scripts]
66+
reactpy = "reactpy._console.cli:entry_point"
67+
6368
[[tool.hatch.build.hooks.build-scripts.scripts]]
6469
# Note: `hatch` can't be called within `build-scripts` when installing packages in editable mode, so we have to write the commands long-form
6570
commands = [
@@ -70,33 +75,23 @@ commands = [
7075
'bun run --cwd "src/js/packages/@reactpy/client" build',
7176
'bun install --cwd "src/js/packages/@reactpy/app"',
7277
'bun run --cwd "src/js/packages/@reactpy/app" build',
73-
'python "src/build_scripts/copy_dir.py" "src/js/packages/@reactpy/app/dist" "src/reactpy/static"',
78+
'python "src/build_scripts/copy_dir.py" "src/js/packages/@reactpy/app/node_modules/@pyscript/core/dist" "src/reactpy/static/pyscript"',
79+
'python "src/build_scripts/copy_dir.py" "src/js/packages/@reactpy/app/node_modules/morphdom/dist" "src/reactpy/static/morphdom"',
7480
]
7581
artifacts = []
7682

77-
[project.optional-dependencies]
78-
all = ["reactpy[jinja,uvicorn,testing]"]
79-
standard = ["reactpy[jinja,uvicorn]"]
80-
jinja = ["jinja2-simple-tags", "jinja2 >=3"]
81-
uvicorn = ["uvicorn[standard]"]
82-
testing = ["playwright"]
83-
8483
#############################
8584
# >>> Hatch Test Runner <<< #
8685
#############################
8786

8887
[tool.hatch.envs.hatch-test]
8988
extra-dependencies = [
89+
"reactpy[all]",
9090
"pytest-sugar",
91-
"pytest-asyncio>=0.23",
92-
"pytest-timeout",
93-
"coverage[toml]>=6.5",
91+
"pytest-asyncio",
9492
"responses",
95-
"playwright",
93+
"exceptiongroup",
9694
"jsonpointer",
97-
"uvicorn[standard]",
98-
"jinja2-simple-tags",
99-
"jinja2 >=3",
10095
"starlette",
10196
]
10297

@@ -156,19 +151,17 @@ serve = [
156151

157152
[tool.hatch.envs.python]
158153
extra-dependencies = [
159-
"ruff",
160-
"toml",
161-
"mypy==1.8",
154+
"reactpy[all]",
155+
"pyright",
162156
"types-toml",
163157
"types-click",
164-
"types-tornado",
165-
"types-flask",
166158
"types-requests",
159+
"types-lxml",
160+
"jsonpointer",
167161
]
168162

169163
[tool.hatch.envs.python.scripts]
170-
# TODO: Replace mypy with pyright
171-
type_check = ["mypy --strict src/reactpy"]
164+
type_check = ["pyright src/reactpy"]
172165

173166
############################
174167
# >>> Hatch JS Scripts <<< #
@@ -193,6 +186,7 @@ test = [
193186
]
194187
build = [
195188
'hatch run "src/build_scripts/clean_js_dir.py"',
189+
'bun install --cwd "src/js"',
196190
'hatch run javascript:build_event_to_object',
197191
'hatch run javascript:build_client',
198192
'hatch run javascript:build_app',
@@ -222,12 +216,8 @@ publish_client = [
222216
# >>> Generic Tools <<< #
223217
#########################
224218

225-
[tool.mypy]
226-
incremental = false
227-
ignore_missing_imports = true
228-
warn_unused_configs = true
229-
warn_redundant_casts = true
230-
warn_unused_ignores = true
219+
[tool.pyright]
220+
reportIncompatibleVariableOverride = false
231221

232222
[tool.coverage.run]
233223
source_pkgs = ["reactpy"]
@@ -237,6 +227,8 @@ omit = [
237227
"src/reactpy/__init__.py",
238228
"src/reactpy/_console/*",
239229
"src/reactpy/__main__.py",
230+
"src/reactpy/pyscript/layout_handler.py",
231+
"src/reactpy/pyscript/component_template.py",
240232
]
241233

242234
[tool.coverage.report]
@@ -252,7 +244,6 @@ exclude_also = [
252244
]
253245

254246
[tool.ruff]
255-
target-version = "py39"
256247
line-length = 88
257248
lint.select = [
258249
"A",
@@ -323,13 +314,7 @@ lint.unfixable = [
323314

324315
[tool.ruff.lint.isort]
325316
known-first-party = ["reactpy"]
326-
327-
[tool.ruff.lint.flake8-tidy-imports]
328-
ban-relative-imports = "all"
329-
330-
[tool.flake8]
331-
select = ["RPY"] # only need to check with reactpy-flake8
332-
exclude = ["**/node_modules/*", ".eggs/*", ".tox/*", "**/venv/*"]
317+
known-third-party = ["js"]
333318

334319
[tool.ruff.lint.per-file-ignores]
335320
# Tests can use magic values, assertions, and relative imports
@@ -346,7 +331,3 @@ exclude = ["**/node_modules/*", ".eggs/*", ".tox/*", "**/venv/*"]
346331
# Allow print
347332
"T201",
348333
]
349-
350-
[tool.black]
351-
target-version = ["py39"]
352-
line-length = 88
8.39 KB
Binary file not shown.

src/js/packages/@reactpy/app/package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@
88
"preact": "^10.25.4"
99
},
1010
"devDependencies": {
11-
"typescript": "^5.7.3"
11+
"typescript": "^5.7.3",
12+
"@pyscript/core": "^0.6",
13+
"morphdom": "^2"
1214
},
1315
"scripts": {
14-
"build": "bun build \"src/index.ts\" --outdir=\"dist\" --minify --sourcemap=\"linked\"",
16+
"build": "bun build \"src/index.ts\" --outdir=\"../../../../reactpy/static/\" --minify --sourcemap=\"linked\"",
1517
"checkTypes": "tsc --noEmit"
1618
}
1719
}

src/js/packages/@reactpy/client/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@reactpy/client",
3-
"version": "0.3.2",
3+
"version": "1.0.0",
44
"description": "A client for ReactPy implemented in React",
55
"author": "Ryan Morshead",
66
"license": "MIT",

src/js/packages/@reactpy/client/src/mount.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export function mountReactPy(props: MountProps) {
88
const wsProtocol = `ws${window.location.protocol === "https:" ? "s" : ""}:`;
99
const wsOrigin = `${wsProtocol}//${window.location.host}`;
1010
const componentUrl = new URL(
11-
`${wsOrigin}${props.pathPrefix}${props.appendComponentPath || ""}`,
11+
`${wsOrigin}${props.pathPrefix}${props.componentPath || ""}`,
1212
);
1313

1414
// Embed the initial HTTP path into the WebSocket URL

src/js/packages/@reactpy/client/src/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export type GenericReactPyClientProps = {
3535
export type MountProps = {
3636
mountElement: HTMLElement;
3737
pathPrefix: string;
38-
appendComponentPath?: string;
38+
componentPath?: string;
3939
reconnectInterval?: number;
4040
reconnectMaxInterval?: number;
4141
reconnectMaxRetries?: number;

0 commit comments

Comments
 (0)