Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
richarddmorey opened this issue Mar 24, 2023 · 4 comments · Fixed by #2251
Closed

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

richarddmorey opened this issue Mar 24, 2023 · 4 comments · Fixed by #2251

Comments

@richarddmorey
Copy link
Sponsor Contributor

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

```{r solutions=TRUE}
4
```

# 1

```{r child='child.Rmd'}
```

# 2

```{r eval=FALSE, child='child.Rmd'}
```

# 3

```{r solutions=TRUE, child='child.Rmd'}
```

# 4

```{r solutions=TRUE, eval=FALSE, child='child.Rmd'}
```

The child document (child.Rmd) is this:

### Here I am

```{r}
a <- 1
```


```{r}
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.

Screenshot 2023-03-24 at 09 54 21

The hook seems to be controlling the chunks within the child document, instead of the chunk itself. Also, in my testing, inline code (via `r `) 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
Copy link
Sponsor Contributor Author

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:

knitr/R/block.R

Lines 58 to 67 in 1239f36

if (!is.null(params$child)) {
if (!is_blank(params[['code']]) && getOption('knitr.child.warning', TRUE)) warning(
"The chunk '", params$label, "' has the 'child' option, ",
"and this code chunk must be empty. Its code will be ignored."
)
if (!params$eval) return('')
cmds = lapply(sc_split(params$child), knit_child, options = block$params)
out = one_string(unlist(cmds))
return(out)
}

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:

knitr/R/block.R

Lines 71 to 81 in 1239f36

ohooks = opts_hooks$get()
for (opt in names(ohooks)) {
hook = ohooks[[opt]]
if (!is.function(hook)) {
warning("The option hook '", opt, "' should be a function")
next
}
if (!is.null(params[[opt]])) params = as.strict_list(hook(params))
if (!is.list(params))
stop("The option hook '", opt, "' should return a list of chunk options")
}

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
Copy link
Owner

yihui commented Apr 21, 2023

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
Copy link
Owner

yihui commented Apr 21, 2023

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

@github-actions
Copy link

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.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Oct 25, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants