yihui / knitr

A general-purpose tool for dynamic report generation in R
https://yihui.org/knitr/
2.37k stars 874 forks source link

knitr options hook with eval does not work as expected with child documents #2247

Closed richarddmorey closed 1 year ago

richarddmorey commented 1 year ago

Summary of the problem: option hooks that control the eval argument don't seem to prevent the eval of child documents, only the chunks within them.

I am compiling (via the RStudio "knit" button) the following Rmd document, which contains an option hook. The params$s parameter controls whether a chunk is evaluated and included, via the option hook. When the solutions hook is included, the chunk should be completely ignored.

However, this does not seem to occur with chunks specifying child Rmd documents. Straight-up eval=FALSE works, but the options hook does not. Instead, the code chunks within the child document are affected by the options hook.

---
output: html_document
params: 
  s: false
---

```{r setup, include=FALSE}

knitr::opts_hooks$set(
  solutions = function(options) {
      options$eval    = params$s
      options$include = params$s
      return(options)
    }
)

0

4

1

2

3

4


The child document (`child.Rmd`) is this:

Here I am

a <- 1
rm(a)

The options hook seems to work for code chunks (ie, `# 0`). I would expect the same results (ie, the child document is not evaluated at all) for chunks under `#2`, `#3`, and `#4`, however, the chunk `#3` shows that the markdown is rendered, but the chunks are not. 

<img width="952" alt="Screenshot 2023-03-24 at 09 54 21" src="https://user-images.githubusercontent.com/1284826/227489067-7a078b85-c18d-4286-8170-7009f60eb816.png">

The hook seems to be controlling the chunks *within* the child document, instead of the chunk itself. Also, in my testing, inline code (via &#96;r &#96;) **is** run, which is a problem when e.g. variables are defined in unevaluated chunks but then printed in (unexpectedly evaluated) inline code in the child chunk.

xfun::session_info() R version 4.2.1 (2022-06-23) Platform: aarch64-apple-darwin20 (64-bit) Running under: macOS Ventura 13.2.1

Locale: en_US.UTF-8 / en_US.UTF-8 / en_US.UTF-8 / C / en_US.UTF-8 / en_US.UTF-8

Package version: base64enc_0.1.3 bslib_0.4.2 cachem_1.0.7 cli_3.6.1 compiler_4.2.1 digest_0.6.31 ellipsis_0.3.2 evaluate_0.20 fastmap_1.1.1 fs_1.6.1
glue_1.6.2 graphics_4.2.1 grDevices_4.2.1 highr_0.10 htmltools_0.5.5 jquerylib_0.1.4 jsonlite_1.8.4 knitr_1.42.5 lifecycle_1.0.3 magrittr_2.0.3 memoise_2.0.1 methods_4.2.1 mime_0.12 R6_2.5.1 rappdirs_0.3.3 remotes_2.4.2 renv_0.17.2 rlang_1.1.0 rmarkdown_2.20 sass_0.4.5
stats_4.2.1 stringi_1.7.12 stringr_1.5.0 tinytex_0.44 tools_4.2.1
utils_4.2.1 vctrs_0.6.1 xfun_0.37 yaml_2.3.7

xfun::session_info('knitr') R version 4.2.1 (2022-06-23) Platform: aarch64-apple-darwin20 (64-bit) Running under: macOS Ventura 13.2.1

Locale: en_US.UTF-8 / en_US.UTF-8 / en_US.UTF-8 / C / en_US.UTF-8 / en_US.UTF-8

Package version: evaluate_0.20 graphics_4.2.1 grDevices_4.2.1 highr_0.10 knitr_1.42.5
methods_4.2.1 stats_4.2.1 tools_4.2.1 utils_4.2.1 xfun_0.37
yaml_2.3.7



---

By filing an issue to this repo, I promise that

- [x ] I have fully read the issue guide at https://yihui.org/issue/.
- [x ] I have provided the necessary information about my issue.
    - If I'm asking a question, I have already asked it on Stack Overflow or RStudio Community, waited for at least 24 hours, and included a link to my question there.
    - If I'm filing a bug report, I have included a minimal, self-contained, and reproducible example, and have also included `xfun::session_info('knitr')`. I have upgraded all my packages to their latest versions (e.g., R, RStudio, and R packages), and also tried the development version: `remotes::install_github('yihui/knitr')`.
    - If I have posted the same issue elsewhere, I have also mentioned it in this issue.
- [ x] I have learned the Github Markdown syntax, and formatted my issue correctly.

I understand that my issue may be closed if I don't fulfill my promises.
richarddmorey commented 1 year ago

Looking at the code in block.R, it appears that this is caused by the fact that the code for chunks for which child is defined is run before the code to get the option hooks: https://github.com/yihui/knitr/blob/1239f36c5dee8b0e029958a793ae71558902f52c/R/block.R#L58-L67

If the chunk option eval=FALSE is set on the chunk, then the chunk correctly returns nothing.

Only after are the option hooks are retrived and added to params:

https://github.com/yihui/knitr/blob/1239f36c5dee8b0e029958a793ae71558902f52c/R/block.R#L71-L81

So in the example, eval has not yet been set to FALSE by the hook when the child code is compiled. The hooks are passed to the chunks in the child document, and so the code chunks are not run there. However, inline code would be.

It seems like an obvious fix would be moving the option hook code above the child code, but that might have other consequences...?

yihui commented 1 year ago

It seems like an obvious fix would be moving the option hook code above the child code, but that might have other consequences...?

Yes, the fix seems obvious. Let's see if #2251 can pass the checks, and also if any reverse dependencies will be broken. Thanks!

yihui commented 1 year ago

Some reverse dependencies were broken, but I think they are irrelevant to this change, so I just merged the PR.

github-actions[bot] commented 8 months ago

This old thread has been automatically locked. If you think you have found something related to this, please open a new issue by following the issue guide (https://yihui.org/issue/), and link to this old issue if necessary.