From ad39413e9c2e30fb59a297ff34150ee60a49c767 Mon Sep 17 00:00:00 2001 From: Carlos Scheidegger Date: Fri, 19 Apr 2024 14:02:06 -0700 Subject: [PATCH 1/4] jupyter - don't merge streams across other output cells. Closes #9422 --- src/core/jupyter/jupyter-fixups.ts | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/src/core/jupyter/jupyter-fixups.ts b/src/core/jupyter/jupyter-fixups.ts index a48c82e7ce4..780a263ebe3 100644 --- a/src/core/jupyter/jupyter-fixups.ts +++ b/src/core/jupyter/jupyter-fixups.ts @@ -23,32 +23,26 @@ export function fixupStreams(nb: JupyterNotebook): JupyterNotebook { if (cell.cell_type !== "code" || cell.outputs === undefined) { continue; } - let i = 0; if (cell.outputs.length === 0) { continue; } + const newOutputs: JupyterOutput[] = [cell.outputs[0]]; + let i = 1; while (i < cell.outputs.length) { + const prevOutput: JupyterOutput = newOutputs[newOutputs.length - 1]; const thisOutput: JupyterOutput = cell.outputs[i]; - if (thisOutput.output_type === "stream") { - // collect all the stream outputs with the same name - const streams = cell.outputs.filter((output) => - output.output_type === "stream" && output.name === thisOutput.name - ); - // join them together - const joinedText = streams.map((output) => output.text ?? []).flat(); - const newOutput: JupyterOutput = { - output_type: "stream", - name: thisOutput.name, - text: joinedText, - }; - cell.outputs[i] = newOutput; - cell.outputs = cell.outputs.filter((output, j) => - i === j || - (output.output_type !== "stream" || output.name !== thisOutput.name) - ); + if ( + thisOutput.output_type === "stream" && + prevOutput.output_type === "stream" && + thisOutput.name === prevOutput.name + ) { + prevOutput.text = [...prevOutput.text ?? [], ...thisOutput.text ?? []]; + } else { + newOutputs.push(thisOutput); } i++; } + cell.outputs = newOutputs; } return nb; } From 0819faeedea95b544e2afbdee74636d6e2d77154 Mon Sep 17 00:00:00 2001 From: Carlos Scheidegger Date: Fri, 19 Apr 2024 14:05:42 -0700 Subject: [PATCH 2/4] regression test --- tests/docs/smoke-all/2024/04/19/9422.qmd | 47 ++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 tests/docs/smoke-all/2024/04/19/9422.qmd diff --git a/tests/docs/smoke-all/2024/04/19/9422.qmd b/tests/docs/smoke-all/2024/04/19/9422.qmd new file mode 100644 index 00000000000..7197afa5e5b --- /dev/null +++ b/tests/docs/smoke-all/2024/04/19/9422.qmd @@ -0,0 +1,47 @@ +--- +title: "Generate Plots within Sub-Sections" +format: + html: + echo: false +# embed-resources: true +engine: jupyter +_quarto: + tests: + html: + ensureHtmlElements: + - ["section#scatter img"] +--- + +```{python} +#| label: setup +import matplotlib.pyplot as plt +``` + +```{python} +#| label: define-data + +data = {'apple': 10, 'orange': 15, 'lemon': 5, 'lime': 20} +names = list(data.keys()) +values = list(data.values()) +``` + +## Plots and Subsections + +```{python} +#| output: asis + +print("\n### Bar\n") + +plt.bar(names, values) +plt.show(block=False) + +print("\n### Scatter\n") + +plt.scatter(names, values) +plt.show(block=False) + +print("\n### Line\n") + +plt.plot(names, values) +plt.show(block=False) +``` From f13fc3dbf18e9a8458184cfeb9a4c5e626db378a Mon Sep 17 00:00:00 2001 From: Carlos Scheidegger Date: Fri, 19 Apr 2024 14:08:59 -0700 Subject: [PATCH 3/4] changelog --- news/changelog-1.5.md | 1 + 1 file changed, 1 insertion(+) diff --git a/news/changelog-1.5.md b/news/changelog-1.5.md index 136d1fa791c..72344c4c20a 100644 --- a/news/changelog-1.5.md +++ b/news/changelog-1.5.md @@ -70,6 +70,7 @@ All changes included in 1.5: - ([#8998](https://github.com/quarto-dev/quarto-cli/issues/8998)): Interpret slide separation markers `---` correctly when creating the `.ipynb` intermediate notebook from a `.qmd` file. - ([#9133](https://github.com/quarto-dev/quarto-cli/issues/9133)): Fix issue with Jupyter engine when using paths containing special characters. - ([#9255](https://github.com/quarto-dev/quarto-cli/issues/9255)): Support cell source fields of type `string`. +- ([#9422](https://github.com/quarto-dev/quarto-cli/issues/9422)): Improve the stream merging algorithm in output cells to avoid merging outputs that should not be merged. ## Website Listings From 9b762d79ac94e8427d41462b54b722078e4bed2a Mon Sep 17 00:00:00 2001 From: Carlos Scheidegger Date: Fri, 19 Apr 2024 14:33:53 -0700 Subject: [PATCH 4/4] allow stream outputs to be string or string[] --- src/core/jupyter/jupyter.ts | 23 ++++++++++++++++++----- src/core/jupyter/types.ts | 4 ++-- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/core/jupyter/jupyter.ts b/src/core/jupyter/jupyter.ts index d39801011ab..f0fdd2779a2 100644 --- a/src/core/jupyter/jupyter.ts +++ b/src/core/jupyter/jupyter.ts @@ -1610,7 +1610,13 @@ async function mdFromCodeCell( if (output.output_type === "stream") { const stream = output as JupyterOutputStream; if (asis && stream.name === "stdout") { - md.push(stream.text.join("")); + let text: string[] = []; + if (typeof stream.text === "string") { + text = [stream.text]; + } else { + text = stream.text; + } + md.push(text.join("")); } else { md.push(mdOutputStream(stream)); } @@ -1750,21 +1756,28 @@ function isMarkdown(output: JupyterOutput, options: JupyterToMarkdownOptions) { } function mdOutputStream(output: JupyterOutputStream) { + let text: string[] = []; + if (typeof output.text === "string") { + text = [output.text]; + } else { + text = output.text; + } + // trim off warning source line for notebook if (output.name === "stderr") { - if (output.text[0]) { - const firstLine = output.text[0].replace( + if (text[0]) { + const firstLine = text[0].replace( /:\d+:\s+/, "", ); return mdCodeOutput( - [firstLine, ...output.text.slice(1)].map(colors.stripColor), + [firstLine, ...text.slice(1)].map(colors.stripColor), ); } } // normal default handling - return mdCodeOutput(output.text.map(colors.stripColor)); + return mdCodeOutput(text.map(colors.stripColor)); } async function mdOutputError( diff --git a/src/core/jupyter/types.ts b/src/core/jupyter/types.ts index 4d273ae117d..e8a78a087a4 100644 --- a/src/core/jupyter/types.ts +++ b/src/core/jupyter/types.ts @@ -166,12 +166,12 @@ export interface JupyterOutput { metadata?: Record; data?: Record; name?: string; - text?: string[]; + text?: string[] | string; } export interface JupyterOutputStream extends JupyterOutput { name: "stdout" | "stderr"; - text: string[]; + text: string[] | string; } export interface JupyterOutputDisplayData extends JupyterOutput {