Repository navigation
Plugin settings form and settings page (M5 part 3a-1 + 3a-2) - #256
Merged
Merged
Conversation
…o a plugin block (M5 part 3a-1) forms.fields() builds the settings form's fields from a plugin's settings description (groups: name, own, common, more); forms.read() turns a sent form into checked changes with an error per field. config_file.set_settings() writes them into one [[plugin]] block (defaults back to comments, read-back check). PluginEditor.save_settings() ties them together. pytest-xdist added as a dev dependency (uv run pytest -n auto). Part of #238 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…et echoed, values over several lines Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
/plugins/<n>/settings shows every setting of a plugin, built from its settings description, in the agreed groups (name; own settings; display time, refresh, layout, level; the rest folded under More settings, open by itself when needed; Technical information with the id). Save applies at once; errors show next to their fields with what was typed. Active Plugins links to it, and adding from the Library opens it. setting(helper=...) names a web helper shown under the field (paperpi.web.helpers; none built in yet). Part of #238 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…More settings rule, tests Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
txoof
previously approved these changes
Oct 9, 2026
Collaborator
Author
|
Folded into #255 (its branch now holds both parts), so one PR merges 3a-1 and 3a-2 together. |
txoof-bot
removed this pull request from stack #257
October 9, 2026 18:30
3 of 4 tasks
txoof
approved these changes
Oct 9, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #238. Both halves of M5 part 3a in one PR (no stack): 3a-1 (form logic, was #255 / #252) and 3a-2 (settings page, was #253). You reviewed both already; the content is unchanged. One squash-merge lands all of it.
Part 3a-1: form logic and saving
What changed
The logic behind the plugin settings form. The page itself comes in 3a-2; this part has no new page yet (like 2b-1 was).
web/forms.pyfields()builds the form's fields from a plugin's settings description: choice list, check box, number (with its limits), text (with its length limit), secret (never put on the page), pick-several list. A setting of a kind the form can't show (a group of settings) is shown as it is in the file, to be changed there.name, then the plugin's own settings, then display time / refresh / layout / level, then the rest ("More settings").read()turns a sent form into the changes to save, or an error next to each field (then nothing is saved). The checks are the plugin's own settings description and the shared one, the same as the config check.config_file.set_settings()writes those changes into one[[plugin]]block as text, keeping everything else.# key = ...comment line, so the help text above it stays.# key = defaultagain.namegoes right belowid.PluginEditor.settings()/save_settings()join these under the config-file lock and apply the change at once. Saving the same form twice writes nothing the second time.uv run pytest -n autoruns the tests on all 4 cores (about 1.5 instead of 4.5 minutes on the Pi).CLAUDE.mdsays when to run which tests.example.toml_value,choicesandplainare now public (the form uses them). Notes added todocs/decisions/web-interface.md.Choices made without asking:
12,-1.5).1_0,nan,1e3and other scripts' digits are refused.Size: +937/−24 (about 960, of which 24 is
uv.lockand about half is tests). That is over the guideline; it grew with the review fixes, which added tests for the cases they found.Area
web (
src/paperpi/web/forms.py,config_file.py,plugins.py), core (example.py: three helpers made public), ci (pyproject.toml,uv.lock: pytest-xdist), docs (CLAUDE.md,docs/decisions/web-interface.md).Tests
New:
tests/test_web_forms.py(fields, groups, kinds, reading, errors, secrets, lists, numbers, shown again after errors), the settings part oftests/test_web_config_file.py(comment lines, defaults, quoted keys, similar keys, values over several lines, CRLF), andsave_settingsintests/test_web_plugins.py.uv run pytestpasses (1416 with the 3a-2 page on top,uv run pytest -n autoon the Pi)uv run ruff check .passesReview
Part 3a-2: the settings page
What changed
The plugin settings page:
/plugins/<n>/settings?id=<id>.namecomes first.id, type, storage folder and the place in the config file.(required)where needed, the setting's key, the limits for numbers, and "Default: …".paperpi.plugin.setting(..., helper="location")names a helper for a setting.paperpi.web.helpers.HELPERSholds a function per name that adds HTML under the field. A name it doesn't know adds nothing, so the plain field still works.location) comes in 3c.docs/writing-plugins.md(which field each setting type gets;helper=),docs/decisions/web-interface.md, the address table inapp.py.Choices made without asking:
Follow-up (not in this PR): some shared help texts were written for the config file ("see Layouts above", "leave it out to use…") and read a little oddly on the page. A later PR can give the page its own short wording.
Area
web (
src/paperpi/web/:app.py,forms.py,helpers.py,plugins.py, templates,style.css), core (plugin.py:setting(helper=),helper_of), docs.Tests
New
tests/test_web_settings.py: link from Active Plugins, groups and folding, saving and applying, errors shown again with nothing saved, check boxes on and off, add → settings page, changed meanwhile, unknown type, out-of-range place, a value not in the choices, secrets never on the page, a list to tick, a read-only setting, the hand-edits note, the helper hook.uv run pytestpasses (1416 on the Pi,-n auto)uv run ruff check .passesImages
No screenshot yet: there is no browser on the Pi in this session. The page's HTML is checked by the tests. I can add a screenshot from another device if you want one.
Review
Only txoof approves and merges this PR.
🤖 Generated with Claude Code