Skip to content

Add theme selection support to HTMLRenderer API and output payload#431

Open
huyhoang171106 wants to merge 3 commits intojoerick:mainfrom
huyhoang171106:feat/add-theme-selection-support-to-htmlrende
Open

Add theme selection support to HTMLRenderer API and output payload#431
huyhoang171106 wants to merge 3 commits intojoerick:mainfrom
huyhoang171106:feat/add-theme-selection-support-to-htmlrende

Conversation

@huyhoang171106
Copy link
Copy Markdown

Summary

Extend HTMLRenderer so users can choose between dark (current default) and light themes when generating HTML. The renderer should validate the option, include the selected theme in the data passed to the frontend app, and preserve backward compatibility by defaulting to dark when unspecified.

Files changed

  • pyinstrument/renderers/html.py (modified)
  • pyinstrument/__main__.py (modified)
  • README.md (modified)

Testing

  • Not run in this environment.

Closes #235

Signed-off-by: Nguyen Huy Hoang <181364121+huyhoang171106@users.noreply.github.com>
Signed-off-by: Nguyen Huy Hoang <181364121+huyhoang171106@users.noreply.github.com>
Signed-off-by: Nguyen Huy Hoang <181364121+huyhoang171106@users.noreply.github.com>
Copilot AI review requested due to automatic review settings March 26, 2026 16:34
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR aims to add a selectable HTML theme (dark default, or light) to HTMLRenderer, validate the option, and include the chosen theme in the payload passed to the bundled frontend so the UI can render accordingly.

Changes:

  • Added a theme parameter to HTMLRenderer and included it in the sessionData payload.
  • Added a --theme CLI option with basic validation.
  • Updated the README changelog to mention theme selection support.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 5 comments.

File Description
pyinstrument/renderers/html.py Adds a theme option and injects it into the JS sessionData payload.
pyinstrument/__main__.py Adds --theme CLI option and validates its value.
README.md Documents the new theme-selection capability in the changelog.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

- Adds the ability to customize description using CLI option `--target-description` (#408)
- You can set the interval for the Django middleware using the PYINSTRUMENT_INTERVAL option (#416)
- HTMLRenderer can now run preprocessors on the input, to manipulate the call tree before writing to HTML (#403)
- HTMLRenderer now supports selecting `dark` or `light` theme via API and CLI, defaulting to `dark`
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the current implementation, the CLI flag isn’t wired into renderer creation and the frontend doesn’t consume the theme field yet, so this changelog entry appears premature/misleading. Either complete the end-to-end support (CLI → renderer → webapp styling) or adjust the README note to match what’s actually shipped.

Suggested change
- HTMLRenderer now supports selecting `dark` or `light` theme via API and CLI, defaulting to `dark`
- Internal plumbing for future `dark` / `light` theme support in HTMLRenderer (not yet exposed via CLI or UI)

Copilot uses AI. Check for mistakes.
options, args = parser.parse_args() # type: ignore
options, args = parser.parse_args()

if options.theme not in ("dark", "light"):
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add/extend CLI tests to cover --theme (valid values are accepted, invalid values error) and verify that the chosen value is passed into HTMLRenderer configuration. There’s already command-line coverage in test/test_cmdline_main.py, so adding a small regression test here will prevent the option from silently becoming a no-op.

Suggested change
if options.theme not in ("dark", "light"):
if options.theme is not None and options.theme not in ("dark", "light"):

Copilot uses AI. Check for mistakes.
Comment on lines +105 to +112
parser.add_option(
"",
"--theme",
dest="theme",
action="store",
default="dark",
help="set HTML theme: dark or light",
)
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

--theme is parsed and validated, but it is never forwarded into the renderer options. As a result, pyinstrument --renderer=html --theme=light will still instantiate HTMLRenderer() with the default theme and the flag has no effect. Pass options.theme through in compute_render_options() when renderer_class is HTMLRenderer (and add theme: str to CommandLineOptions so type-checking matches the CLI surface).

Copilot uses AI. Check for mistakes.

<script>
const sessionData = {session_json};
const sessionData = {...{session_json}, theme: {json.dumps(self.theme)}};
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The frontend bundle currently doesn’t reference a theme field (and app.css hard-codes dark colors), so adding theme to sessionData won’t actually change the rendered appearance. To make theme selection functional, the webapp needs to read sessionData.theme and apply the corresponding class/CSS variables (or ship separate CSS) during render.

Suggested change
const sessionData = {...{session_json}, theme: {json.dumps(self.theme)}};
const sessionData = {...{session_json}};

Copilot uses AI. Check for mistakes.

<script>
const sessionData = {session_json};
const sessionData = {...{session_json}, theme: {json.dumps(self.theme)}};
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const sessionData = {...<large object>...} forces creation of an extra object via spread, which can add noticeable memory/CPU overhead for large profiles (this payload can be huge). Consider keeping the original assignment and then setting sessionData.theme (or embedding the theme in the JSON string on the Python side) to avoid copying properties.

Suggested change
const sessionData = {...{session_json}, theme: {json.dumps(self.theme)}};
const sessionData = JSON.parse('{session_json}');
sessionData.theme = {json.dumps(self.theme)};

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

HTML light mode

2 participants