Closed nwstephens closed 3 years ago
I believe this is due to rstudioapi::askForSecret
iself
rstudioapi::askForSecret <- function (name, message = paste(name, ":", sep = ""), title = paste(name, "Secret")) {
if (hasFun("askForSecret")) {
callFun("askForSecret", name, title, message)
}
else {
askForPassword(message)
}
}
As seen above, askForPassword
is the fallback when hasFun("askForSecret")
is FALSE.
And the latter is TRUE when use interactively in RStudio, which is why it works when you click the green arrow run chunk button, but FALSE in a non interactive R session, which is what happens when you click the Knit button
# in a non interactive session
callr::r(function() rstudioapi:::hasFun("askForSecret"))
#> [1] FALSE
# inside an interactive session
rstudioapi:::hasFun("askForSecret")
#> [1] TRUE
I don't think it a keyring or rmardown issue currently.
Thanks, @cderv . Any ideas why callr::r(function() rstudioapi:::hasFun("askForSecret"))
returns FALSE
? It would be better in this case if it returned TRUE
.
You cannot use rstudioapi from a subprocess.
@nwstephens, as said just ☝️ , yes with callr, it returns FALSE because it is a subprocess and rstudioapi won't work because RStudio is not running. So it is expected that hasFun()
returns FALSE as its first check will be rstudioapi::isAvailable()
. You'll get the same with rstudioapi::askForPassword()
if run explicitly in a subprocess
> callr::r(function() rstudioapi::askForPassword())
Error: callr subprocess failed: RStudio not running
I am just surprised that in you video, this works when Knitting a Rmd document in the IDE because the IDE will call rmarkdown::render()
in a subprocess. So I had a closer look at the source of function in rstudioapi
So it seems rstudioapi has a special handling for child processes of RStudio IDE (when Knitting or when running Jobs maybe - I don't really know) and that is why rstudioapi::askForPassword()
is working
See rstudioapi::callFun
which is handling the call to all RStudio function: https://github.com/rstudio/rstudioapi/blob/8ed4d50a0a471737337c503069857fb217661cb1/R/code.R#L92-L95. It will do a special thing when child process of RStudio is detected.
So this would work as you expect in a Rmd file knitted in the IDE:
---
title: "rstudioapi in Rmd"
output: html_document
---
This will be TRUE when rendered with Knit button and FALSE if outside of RStudio
```{r}
rstudioapi:::isChildProcess()
but rstudio is not available
rstudioapi::isAvailable()
unless explicitly asking for child process handling
rstudioapi::isAvailable(child_ok = TRUE)
askForSecret
would work as askForPassword
if call this way
rstudioapi::callFun("askForSecret", "test", "test:", "test Secret")
But this seems a bit hacky as this document would error is not knitted in RStudio IDE but in another interactive session.
but when you call `rstudioapi::askForSecret()`, it does not behave this way because of check with `rstudioapi::hasFun()`
Anyway, I think this is something to discuss with the IDE team about this usage and **rstudioapi** behavior.
This was the response from Kevin Ushey
This is because rstudioapi functions are only available in the RStudio main process, or in certain RStudio jobs. I don't think they're visible to the R process used for knit.
Which leads me to ask, "What is the intended behavior of askForSecret with knit -- throw an error?"
I don't think they're visible to the R process used for knit.
It seems that rstudioapi::askForPassword()
is seen by R process used for knit. From your answer @kevinushey, I understand that this may not be expected ? As explain above, it seems callFun
is working when knitting inside RStudio because it is seen as a child process of RStudio.
Which leads me to ask, "What is the intended behavior of askForSecret with knit -- throw an error?"
This is a discussion we should have in rstudioapi repo I guess: Are functions from rstudioapi supposed to work within an R Markdown document knitted in the IDE ? Maybe this discussion should move there ? (not sure it is possible between organization to move issues though)
I tend to say this is not a good idea as it will not be portable. The document would error if any function from rstudioapi is used in the document, but you render it outside of RStudio. If you render a document like in a background jobs also I am not sure this is supposed to open a user interface to enter a password.
However, I see the need for a window opening to provide secret informations. FWIW there is another feature I see that works already with Rmd only when inside RStudio which offers a user interface: it is parameterized report: https://bookdown.org/yihui/rmarkdown/params-knit.html#the-interactive-user-interface Using a connection to DB inside a Rmd document interactively will also open the connection pane I believe.
Looking at this a bit more closely (with @cderv's helpful output) this is indeed an issue with the way that rstudioapi::askForSecret
is implemented. It should work for documented run via Knit, but doesn't because hasFun()
reports that the function doesn't exist.
I'll see if I can fix this -- I think this is ultimately an rstudioapi
issue.
Should now be fixed -- install the development version of rstudioapi
with remotes::install_github("rstudio/rstudioapi")
. I see e.g.:
Thanks @kevinushey. I verified that this issue has been resolved with implemented changes to the rstudioapi
package.
For some reason hitting the knitr button in the RStudio IDE unexpectedly prompts the user for a password instead of a secret. Steps to reproduce:
rstudioapi::askForSecret("test")
into a code chunkResult: The IDE prompts for a password instead of a secrete. See here for a video.
I would expect the knit button to ask for a secret, not a password.
Note: Running the code chunk or rendering the code chunk with rmarkdown::render() still works. Only the knit button delivers a different experience.