Skip to content

fix(jupyter): run {ggsql} cells; expand {resource_dir} in kernelspec argv - #864

Merged
gordonwoodhull merged 3 commits into
mainfrom
bugfix/ggsql-executable-language
Oct 17, 2026
Merged

gordonwoodhull merged 3 commits into
mainfrom
bugfix/ggsql-executable-language

Conversation

@gordonwoodhull

@gordonwoodhull gordonwoodhull commented Oct 17, 2026 •

Copy link
Copy Markdown
Member

Summary

{ggsql} code blocks never ran under q2 render. The Jupyter engine passed them through as literal text, because it executes only the languages named in a hard-coded list. Once that list allows ggsql, a second defect appears: the kernel fails to start, because q2 never expands the {resource_dir} placeholder in the kernelspec's argv. This PR fixes both. It also adds an outline for removing the language list altogether.

The two fixes

  1. Allowlist. is_executable_language (engine/jupyter/text_execute.rs) now includes ggsql. The kernel name needs no mapping: map_language_to_kernel already passes unknown language names through, and the ggsql kernelspec is named ggsql.
  2. {resource_dir}. runtimelib substitutes only {connection_file} in argv, but the Jupyter kernelspec contract also defines {resource_dir} (the kernelspec's own directory). The ggsql kernelspec launches {resource_dir}/ggsql-jupyter, so spawning failed with No such file or directory. expand_resource_dir (engine/jupyter/daemon.rs) now expands it, using an absolute path. This applies to any kernel that uses the placeholder, not only ggsql.

Known limitation

A document gets one kernel, chosen from its first executable cell. A document that mixes {python} and {ggsql} therefore sends every cell to the first cell's kernel, and the other language's cells fail. Before this PR those ggsql cells were left unexecuted (or reported as unhandled in a multi-engine document), so this is a visible change in behavior for mixed documents.

Longer-term fix (outline only)

The language allowlist is a stopgap. The resolver already assigns ggsql to the Jupyter engine, but the engine never receives that assignment. It receives only the set of languages to leave alone, so it cannot tell "mine" from "owned by nobody" and falls back on its own list.

claude-notes/plans/2026-10-17-jupyter-owned-languages-epic.md outlines an epic that would:

  • pass each engine the languages it owns (absorbing Plan 4d's owned_languages);
  • find kernels the way Quarto 1 does, by matching the kernelspec's language field;
  • possibly support several kernels in one document.

The multi-kernel part is a stretch goal. It goes beyond Quarto 1, which runs one kernel per document, and it needs further design and discussion before anyone plans it in detail. The rest of the outline stands without it. The plan records what we verified, the decisions so far, and the open questions. It is an outline for review, not a commitment to this design.

Testing

  • Unit tests: ggsql in test_is_executable_language, plus two tests for expand_resource_dir (substitution; other args left alone).
  • cargo clippy -p quarto-core --all-targets -- -D warnings is clean. cargo nextest run -p quarto-core passed (6300 tests) before the final review fixes; after them I re-ran only the 109 jupyter tests.
  • q2 render --strict passes on the plan file.
  • By hand, with a locally built ggsql kernel (v0.5.2): a bar chart, a scatter plot with labels, and a three-block document (create a table, query it, plot it) all render, and the session carries across blocks. Before this PR the same documents rendered the blocks as literal text.
  • Not tested: a mixed python and ggsql document with this fix, and the PyPI-installed kernel.

@icarusz

…elspec argv

Add ggsql to the jupyter engine's executable-language allowlist, so
{ggsql} blocks run on the ggsql kernel instead of passing through as
literal text.

runtimelib substitutes only {connection_file} in a kernelspec's argv,
but the Jupyter kernelspec contract also defines {resource_dir}, which
the ggsql kernelspec uses ({resource_dir}/ggsql-jupyter). Expand it
(absolutized) before spawning the kernel.

Known limitation: one kernel is chosen per document from the first
executable cell, so mixing {python} and {ggsql} still fails.
…i-kernel

Replace the Jupyter engine's hard-coded language lists with
resolver-assigned ownership (absorbing Plan 4d), Q1-style kernelspec
lookup by language, and several kernels per document. Records the
research, decisions, and open questions so far.
@posit-snyk-bot

posit-snyk-bot commented Oct 17, 2026 •

Copy link
Copy Markdown
Contributor

✅ Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
✅ Open Source Security 0 0 0 0 0 issues
✅ Licenses 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@gordonwoodhull
gordonwoodhull merged commit 3eddb01 into main Oct 17, 2026
14 checks passed
@gordonwoodhull
gordonwoodhull deleted the bugfix/ggsql-executable-language branch October 17, 2026 20:17
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.

2 participants