rmarkdown icon indicating copy to clipboard operation
rmarkdown copied to clipboard

`rmarkdown::render` fails when code chunks contain `sink(...)`

Open Patrick330 opened this issue 2 years ago • 3 comments

Context

I am writing a package that implements a standardized logging function using sink(...). I would like to be able to use RMarkdown to write the vignettes for the package.

Issue

Code chunks containing sink(...) commands do not sink if not followed in the same ~~line~~ expression by a sink() command closing the new connection. This is due to evaluate's use of sink() to capture output. See issue opened with evaluate: https://github.com/r-lib/evaluate/issues/104

See also this relevant Stack Overflow issue: https://stackoverflow.com/questions/39131017/sink-wont-print-output-to-text-file-in-rmarkdown

Proposed resolution

One option would be to modify the evaluate package so that these conditions throw an error and then have rmarkdown handle that error with either a warning to the user or by executing the sink(...) statement with eval().

Alternately rmarkdown could identify offending statements separately.

Reprex

Submit the following Rmd file via rmarkdown::render() or by clicking the "knit" button in Rstudio:

---
title: "Untitled"
output: html_document
---

# Log `sessionInfo()`

```{r}
log_path <- file.path(tempdir(), 'temp.log')
sink(log_path)
print(sessionInfo())
sink()
```

# Did it work?

```{r}
readLines(log_path)
```

The final line will indicate that the log was empty and sink(...) failed: ## character(0)

In contrast, if you run the chunks interactively with the Rstudio "Run chunk" commands, the log contains the expected output of sessionInfo().

xfun::sessionInfo()

R version 4.1.2 (2021-11-01) Platform: x86_64-w64-mingw32/x64 (64-bit) Running under: Windows 10 x64 (build 19043), RStudio 2021.9.0.351

Locale: LC_COLLATE=English_United States.1252 LC_CTYPE=English_United States.1252 LC_MONETARY=English_United States.1252 LC_NUMERIC=C LC_TIME=English_United States.1252

Package version: base64enc_0.1.3 bslib_0.3.1 compiler_4.1.2 digest_0.6.28 evaluate_0.14 fastmap_1.1.0
fs_1.5.0 glue_1.4.2 graphics_4.1.2 grDevices_4.1.2 highr_0.9 htmltools_0.5.2 jquerylib_0.1.4 jsonlite_1.7.2 knitr_1.36 magrittr_2.0.1 methods_4.1.2 R6_2.5.1
rappdirs_0.3.3 rlang_0.4.12 rmarkdown_2.11.3 rstudioapi_0.13 sass_0.4.0 stats_4.1.2
stringi_1.7.5 stringr_1.4.0 tinytex_0.35 tools_4.1.2 utils_4.1.2 xfun_0.27
yaml_2.2.1

Checklist

When filing a bug report, please check the boxes below to confirm that you have provided us with the information we need. Have you:

  • [X] formatted your issue so it is easier for us to read?

  • [X] included a minimal, self-contained, and reproducible example?

  • [X] pasted the output from xfun::session_info('rmarkdown') in your issue?

  • [X] upgraded all your packages to their latest versions (including your versions of R, the RStudio IDE, and relevant R packages)?

  • [X] installed and tested your bug with the development version of the rmarkdown package using remotes::install_github("rstudio/rmarkdown")?

Patrick330 avatar Nov 05 '21 05:11 Patrick330

Would someone be able to triage this?

Patrick330 avatar Jan 06 '22 20:01 Patrick330

Try curly braces around your code block.

---
title: "Untitled"
output: html_document
---

# Log `sessionInfo()`

```{r}
{
log_path <- file.path(tempdir(), 'temp.log')
sink(log_path)
print(sessionInfo())
sink()
}
```

# Did it work?

```{r}
readLines(log_path)
```

dschmidt-hgu avatar Apr 14 '22 11:04 dschmidt-hgu

@dschmidt-hgu Thank you for the suggestion. It does indeed correct the issue in the reproducible example I provided. Unfortunately it does not address the underlying issue:

Code chunks containing sink(...) commands do not sink if not followed in the same line by a sink() command closing the new connection.

By wrapping the statement in curly braces we are simply reducing multiple lines to a single expression, with the same effect as if we had included the closing sink() statement in the same line following a semicolon. So perhaps we should modify the issue to read:

Code chunks containing sink(...) commands do not sink if not followed in the same ~~line~~ expression by a sink() command closing the new connection.

Patrick330 avatar May 04 '22 13:05 Patrick330