Skip to content

Commit 341a492

Browse files
authored
Concurrent Renders (#1165)
* initial work on concurrent renders * concurrent renders * limit to 3.11 * fix docs * update changelog * simpler add_effect interface * improve docstring * better changelog description * effect function accepts stop event * simplify concurrent render process * test serial renders too * remove ready event * fix doc example * add docstrings * use function scope async fixtures * fix flaky test * rename config option * move effect kick-off into component did render * move effect start to back to layout render * try 3.x again * require tracerite 1.1.1 * fix docs build
1 parent 701e462 commit 341a492

File tree

21 files changed

+685
-569
lines changed

21 files changed

+685
-569
lines changed

.github/workflows/.hatch-run.yml

+54-54
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,59 @@
11
name: hatch-run
22

33
on:
4-
workflow_call:
5-
inputs:
6-
job-name:
7-
required: true
8-
type: string
9-
hatch-run:
10-
required: true
11-
type: string
12-
runs-on-array:
13-
required: false
14-
type: string
15-
default: '["ubuntu-latest"]'
16-
python-version-array:
17-
required: false
18-
type: string
19-
default: '["3.x"]'
20-
node-registry-url:
21-
required: false
22-
type: string
23-
default: ""
24-
secrets:
25-
node-auth-token:
26-
required: false
27-
pypi-username:
28-
required: false
29-
pypi-password:
30-
required: false
4+
workflow_call:
5+
inputs:
6+
job-name:
7+
required: true
8+
type: string
9+
hatch-run:
10+
required: true
11+
type: string
12+
runs-on-array:
13+
required: false
14+
type: string
15+
default: '["ubuntu-latest"]'
16+
python-version-array:
17+
required: false
18+
type: string
19+
default: '["3.x"]'
20+
node-registry-url:
21+
required: false
22+
type: string
23+
default: ""
24+
secrets:
25+
node-auth-token:
26+
required: false
27+
pypi-username:
28+
required: false
29+
pypi-password:
30+
required: false
3131

3232
jobs:
33-
hatch:
34-
name: ${{ format(inputs.job-name, matrix.python-version, matrix.runs-on) }}
35-
strategy:
36-
matrix:
37-
python-version: ${{ fromJson(inputs.python-version-array) }}
38-
runs-on: ${{ fromJson(inputs.runs-on-array) }}
39-
runs-on: ${{ matrix.runs-on }}
40-
steps:
41-
- uses: actions/checkout@v2
42-
- uses: actions/setup-node@v2
43-
with:
44-
node-version: "14.x"
45-
registry-url: ${{ inputs.node-registry-url }}
46-
- name: Pin NPM Version
47-
run: npm install -g [email protected]
48-
- name: Use Python ${{ matrix.python-version }}
49-
uses: actions/setup-python@v2
50-
with:
51-
python-version: ${{ matrix.python-version }}
52-
- name: Install Python Dependencies
53-
run: pip install hatch poetry
54-
- name: Run Scripts
55-
env:
56-
NODE_AUTH_TOKEN: ${{ secrets.node-auth-token }}
57-
PYPI_USERNAME: ${{ secrets.pypi-username }}
58-
PYPI_PASSWORD: ${{ secrets.pypi-password }}
59-
run: hatch run ${{ inputs.hatch-run }}
33+
hatch:
34+
name: ${{ format(inputs.job-name, matrix.python-version, matrix.runs-on) }}
35+
strategy:
36+
matrix:
37+
python-version: ${{ fromJson(inputs.python-version-array) }}
38+
runs-on: ${{ fromJson(inputs.runs-on-array) }}
39+
runs-on: ${{ matrix.runs-on }}
40+
steps:
41+
- uses: actions/checkout@v2
42+
- uses: actions/setup-node@v2
43+
with:
44+
node-version: "14.x"
45+
registry-url: ${{ inputs.node-registry-url }}
46+
- name: Pin NPM Version
47+
run: npm install -g [email protected]
48+
- name: Use Python ${{ matrix.python-version }}
49+
uses: actions/setup-python@v2
50+
with:
51+
python-version: ${{ matrix.python-version }}
52+
- name: Install Python Dependencies
53+
run: pip install hatch poetry
54+
- name: Run Scripts
55+
env:
56+
NODE_AUTH_TOKEN: ${{ secrets.node-auth-token }}
57+
PYPI_USERNAME: ${{ secrets.pypi-username }}
58+
PYPI_PASSWORD: ${{ secrets.pypi-password }}
59+
run: hatch run ${{ inputs.hatch-run }}

.github/workflows/check.yml

+43-40
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,48 @@
11
name: check
22

33
on:
4-
push:
5-
branches:
6-
- main
7-
pull_request:
8-
branches:
9-
- main
10-
schedule:
11-
- cron: "0 0 * * 0"
4+
push:
5+
branches:
6+
- main
7+
pull_request:
8+
branches:
9+
- main
10+
schedule:
11+
- cron: "0 0 * * 0"
1212

1313
jobs:
14-
test-py-cov:
15-
uses: ./.github/workflows/.hatch-run.yml
16-
with:
17-
job-name: "python-{0}"
18-
hatch-run: "test-py"
19-
lint-py:
20-
uses: ./.github/workflows/.hatch-run.yml
21-
with:
22-
job-name: "python-{0}"
23-
hatch-run: "lint-py"
24-
test-py-matrix:
25-
uses: ./.github/workflows/.hatch-run.yml
26-
with:
27-
job-name: "python-{0} {1}"
28-
hatch-run: "test-py --no-cov"
29-
runs-on-array: '["ubuntu-latest", "macos-latest", "windows-latest"]'
30-
python-version-array: '["3.9", "3.10", "3.11"]'
31-
test-docs:
32-
uses: ./.github/workflows/.hatch-run.yml
33-
with:
34-
job-name: "python-{0}"
35-
hatch-run: "test-docs"
36-
test-js:
37-
uses: ./.github/workflows/.hatch-run.yml
38-
with:
39-
job-name: "{1}"
40-
hatch-run: "test-js"
41-
lint-js:
42-
uses: ./.github/workflows/.hatch-run.yml
43-
with:
44-
job-name: "{1}"
45-
hatch-run: "lint-js"
14+
test-py-cov:
15+
uses: ./.github/workflows/.hatch-run.yml
16+
with:
17+
job-name: "python-{0}"
18+
hatch-run: "test-py"
19+
lint-py:
20+
uses: ./.github/workflows/.hatch-run.yml
21+
with:
22+
job-name: "python-{0}"
23+
hatch-run: "lint-py"
24+
test-py-matrix:
25+
uses: ./.github/workflows/.hatch-run.yml
26+
with:
27+
job-name: "python-{0} {1}"
28+
hatch-run: "test-py --no-cov"
29+
runs-on-array: '["ubuntu-latest", "macos-latest", "windows-latest"]'
30+
python-version-array: '["3.9", "3.10", "3.11"]'
31+
test-docs:
32+
uses: ./.github/workflows/.hatch-run.yml
33+
with:
34+
job-name: "python-{0}"
35+
hatch-run: "test-docs"
36+
# as of Dec 2023 lxml does have wheels for 3.12
37+
# https://bugs.launchpad.net/lxml/+bug/2040440
38+
python-version-array: '["3.11"]'
39+
test-js:
40+
uses: ./.github/workflows/.hatch-run.yml
41+
with:
42+
job-name: "{1}"
43+
hatch-run: "test-js"
44+
lint-js:
45+
uses: ./.github/workflows/.hatch-run.yml
46+
with:
47+
job-name: "{1}"
48+
hatch-run: "lint-js"

docs/source/about/changelog.rst

+6
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ Unreleased
2828
- :pull:`1118` - `module_from_template` is broken with a recent release of `requests`
2929
- :pull:`1131` - `module_from_template` did not work when using Flask backend
3030

31+
**Added**
32+
33+
- :pull:`1165` - Allow concurrent renders of discrete component tree - enable this
34+
experimental feature by setting `REACTPY_ASYNC_RENDERING=true`. This should improve
35+
the overall responsiveness of your app, particularly when handling larger renders
36+
that would otherwise block faster renders from being processed.
3137

3238
v1.0.2
3339
------

src/py/reactpy/pyproject.toml

+3-1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ starlette = [
4545
sanic = [
4646
"sanic >=21",
4747
"sanic-cors",
48+
"tracerite>=1.1.1",
49+
"setuptools",
4850
"uvicorn[standard] >=0.19.0",
4951
]
5052
fastapi = [
@@ -80,7 +82,7 @@ pre-install-command = "hatch build --hooks-only"
8082
dependencies = [
8183
"coverage[toml]>=6.5",
8284
"pytest",
83-
"pytest-asyncio>=0.17",
85+
"pytest-asyncio>=0.23",
8486
"pytest-mock",
8587
"pytest-rerunfailures",
8688
"pytest-timeout",

src/py/reactpy/reactpy/_option.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,10 @@ def current(self) -> _O:
6868
def current(self, new: _O) -> None:
6969
self.set_current(new)
7070

71+
@current.deleter
72+
def current(self) -> None:
73+
self.unset()
74+
7175
def subscribe(self, handler: Callable[[_O], None]) -> Callable[[_O], None]:
7276
"""Register a callback that will be triggered when this option changes"""
7377
if not self.mutable:
@@ -123,7 +127,8 @@ def unset(self) -> None:
123127
msg = f"{self} cannot be modified after initial load"
124128
raise TypeError(msg)
125129
old = self.current
126-
delattr(self, "_current")
130+
if hasattr(self, "_current"):
131+
delattr(self, "_current")
127132
if self.current != old:
128133
for sub_func in self._subscribers:
129134
sub_func(self.current)

src/py/reactpy/reactpy/backend/hooks.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
from typing import Any
55

66
from reactpy.backend.types import Connection, Location
7-
from reactpy.core.hooks import Context, create_context, use_context
7+
from reactpy.core.hooks import create_context, use_context
8+
from reactpy.core.types import Context
89

910
# backend implementations should establish this context at the root of an app
1011
ConnectionContext: Context[Connection[Any] | None] = create_context(None)

src/py/reactpy/reactpy/config.py

+8
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,11 @@ def boolean(value: str | bool | int) -> bool:
8080
validator=float,
8181
)
8282
"""A default timeout for testing utilities in ReactPy"""
83+
84+
REACTPY_ASYNC_RENDERING = Option(
85+
"REACTPY_CONCURRENT_RENDERING",
86+
default=False,
87+
mutable=True,
88+
validator=boolean,
89+
)
90+
"""Whether to render components concurrently. This is currently an experimental feature."""

0 commit comments

Comments
 (0)