Skip to content

Commit 0decbc3

Browse files
committed
docs: fix stale CI/pin claims, a leaking include marker, and two reducer/context claims
- about/running-tests.md: docs/requirements.txt has pinned mkdocs-material==9.7.7 since 78f1dd0; the paragraph still described 9.4.0's regex~=2022.4 cp311 cap, which no longer applies (9.7.x drops regex entirely). Reworded as history. - about/code.md: 'docs PRs get no CI' gave one vague reason; there are two concrete ones (PR workflows run from the base branch, and check.yml's test-documentation job is gated behind 'if: 0'), and the push-deploy that does run is gh-deploy --force without --strict. - tutorial_tic_tac_toe/mutating/app.py: a stray indented '# start' after the first marker survived the include crop and printed on the rendered page. - extracting-state-logic: a raising reducer is not 'swallowed with no log entry' -- logger.exception in Layout._process_event_queue writes 'Failed to execute event handler' with a traceback to the reactpy.core.layout logger. Verified with a capturing handler: zero renders, one ERROR record. - scaling-up-with-reducer-and-context: context values are not compared with ==; use_context returns provider.value verbatim, so keeping the value object stable buys nothing (measured: consumer re-rendered with a literally identical value).
1 parent c5c2e10 commit 0decbc3

5 files changed

Lines changed: 5 additions & 6 deletions

File tree

‎docs/examples/tutorial_tic_tac_toe/mutating/app.py‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ def inner(event):
2222

2323
return inner
2424

25-
# start
2625
return html.fragment(
2726
html.div(
2827
{"className": "board-row"},

‎docs/src/about/code.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ hatch test -k the_test_you_touched
8686

8787
CI retries flaky tests, which is a mercy and a trap: a genuinely racy test can go green on the third attempt and stay in the tree. If a test fails once and passes on retry, that is a bug in the test — usually a bare `asyncio.sleep` where `poll(...)` belongs.
8888

89-
Documentation pull requests get no CI at all. The workflow set on `main` runs against `main`, and the only workflow on `new-docs` deploys on push without `--strict`. So a docs change is verified by you or by nobody — run the `mkdocs build --strict` set from [Running Tests](./running-tests.md) and read its exit code, then expect the change to be live the moment it merges.
89+
A pull request into `new-docs` gets no CI at all, for two independent reasons. GitHub runs `pull_request` workflows from the **base** branch, and the only workflow that exists on `new-docs` is the docs deploy, which triggers on `push` — so nothing matches a PR. And the `test-documentation` job in `check.yml` on `main` is disabled outright with `if: 0` (temporarily, while the Sphinx-to-MkDocs transition finishes), so even a PR targeting `main` runs lint and Python tests but never builds the docs. A docs change is verified by you or by nobody — run the `mkdocs build --strict` set from [Running Tests](./running-tests.md) and read its exit code. The one thing that does run: pushing to `new-docs` deploys with `mkdocs gh-deploy --force`, no `--strict` — expect a change to be live the moment it merges, whether or not it builds cleanly.
9090

9191
## Working with reviewers
9292

‎docs/src/about/running-tests.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ cd docs && mkdocs serve
139139

140140
Then follow the printed URL. Editing any file under `docs/src/` or `docs/examples/` reloads the page.
141141

142-
The requirements file pins `mkdocs-material==9.4.0`, which transitively pins `regex==2022.10.31`. That release ships wheels only through CPython 3.11, so on 3.12 and newer the install falls back to a source build and fails without a C compiler. If the docs install dies inside `regex`, use Python 3.11 or install a newer `mkdocs-material` — nothing in these pages depends on the pin.
142+
The requirements file pins `mkdocs-material==9.7.7`. Earlier revisions pinned `9.4.0`, which pulled in `regex~=2022.4` and resolved to a release shipping wheels only through CPython 3.11 — on newer Pythons that meant a source build and a hard failure without a C compiler. The current pin dropped the `regex` dependency altogether, so the install works on 3.12 and up. If you are on an older branch and the docs install dies inside `regex`, that is the reason: use Python 3.11 or raise the pin.
143143

144144
## Checking your work
145145

‎docs/src/learn/extracting-state-logic-into-a-reducer.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ Verified trace of one click. `#!python dispatch` calls your reducer *immediately
130130

131131
Three consequences:
132132

133-
- **A reducer that raises is swallowed.** Verified: dispatching an action whose branch raises `#!python ValueError` leaves the state untouched, produces zero renders, and logs nothing under the `#!python reactpy` logger — only a root-logger `#!python ERROR: Failed to execute event handler` line. The component stays mounted and keeps working for later actions. This is the loudest failure the pattern has, and it is still quiet.
133+
- **A reducer that raises surfaces as a failed event handler, not a reducer error.** Verified: dispatching an action whose branch raises `#!python ValueError` leaves the state untouched and produces zero renders. `#!python dispatch` ran the reducer inside the handler, so the exception propagates to `core/layout.py`, `Layout._process_event_queue`, which catches it and calls `#!python logger.exception` — one `#!python ERROR: Failed to execute event handler` record on the `#!python reactpy.core.layout` logger, with the reducer's traceback attached. ReactPy itself never reports "a reducer raised". The component stays mounted and keeps working for later actions.
134134
- **Multiple dispatches in one handler batch into one render.** Verified: three `#!python dispatch` calls in a single handler produce three reducer calls, applied in order, and **one** render.
135135
- **Purity is not optional, but for a different reason than in React.** Since the result is compared with `==`, mutating and returning the same object compares equal and schedules nothing.
136136

@@ -183,7 +183,7 @@ Use a reducer when a component has produced real bugs from the wrong update path
183183
- Therefore define reducers at **module level**, reading nothing but `#!python state` and `#!python action`. A reducer defined in the component body freezes its closure — verified charging `#!python total=20` at a displayed `#!python price=50`.
184184
- `#!python dispatch` runs the reducer **immediately**, inside the handler, not at the next render. Verified by trace.
185185
- Mutating the state and returning it compares equal, so nothing renders — verified: three presses, zero renders, no log line. Return new objects.
186-
- A raising reducer is swallowed with no `#!python reactpy` log entry; end the reducer with `#!python raise ValueError` so unknown actions surface.
186+
- A raising reducer surfaces as `#!python ERROR: Failed to execute event handler` from `#!python reactpy.core.layout`, not as a reducer error; end the reducer with `#!python raise ValueError` so unknown actions surface.
187187
- Several dispatches in one handler apply in order and cost one render (verified).
188188
- `use_reducer` takes two arguments; pass a callable as `#!python initial_value` to build it lazily, once.
189189

‎docs/src/learn/scaling-up-with-reducer-and-context.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ state, dispatch = use_reducer(tasks_reducer, INITIAL_STATE)
7070
TaskContext(task_list(), value=(state, dispatch))
7171
```
7272

73-
A tuple is the simplest value that carries both. If you prefer a dict or a dataclass, the same rules apply — but keep it a fresh object each render, since ReactPy compares the provided value with `==`, and an action that changes nothing should not re-render anything.
73+
A tuple is the simplest value that carries both. If you prefer a dict or a dataclass, the same rules apply — but do not expect the value to control how often consumers render. ReactPy compares nothing here: `use_context` hands back whatever the provider is currently holding, and a provider that re-renders re-renders its children whether the value is new, equal, or literally the same object. Re-render cost is governed by where you place the provider, not by how you build the value.
7474

7575
### Step 3: Use context anywhere in the tree
7676

0 commit comments

Comments
 (0)