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

webr::global_prompt_install() not working with webR.evalR() #324

Closed
christianp opened this issue Nov 22, 2023 · 7 comments · Fixed by #371
Closed

webr::global_prompt_install() not working with webR.evalR() #324

christianp opened this issue Nov 22, 2023 · 7 comments · Fixed by #371
Labels
bug Something isn't working

Comments

@christianp
Copy link

The WebR support package has a function webr::global_prompt_install() which will interactively prompt you to install a package before loading it.
Is there a way of getting WebR to automatically install packages without a prompt? Or could I write my own shim round library() to do this?

@georgestagg
Copy link
Member

The webr::global_prompt_install() command takes an argument show_menu. When this is set to FALSE, webR should skip the menu and just attempt to download the package instead.

@georgestagg georgestagg added the question Further information is requested label Nov 22, 2023
@christianp
Copy link
Author

Ah, thanks!

@georgestagg
Copy link
Member

[..] install packages in an allowed list [...]

Ah, I just saw this part of the question! There's no support for an allow-list, I think you'd have to implement that yourself.

You might be able to use renv::dependencies() as an alternative to shimming require() and library(), then once you have your list filter it down and use webr::install() in R or webR.installPackages().

@christianp
Copy link
Author

Hrm: when I run that, I get "WebRWorkerError: should not be called with handlers on the stack".
Here's a minimal page that just loads webR and tries to run webr::global_prompt_install(): https://darkened-opalescent-asphalt.glitch.me/
Clearly I'm doing something wrong, but what?

@georgestagg
Copy link
Member

Ah yes, there's a gap in documentation here, sorry. To install the new global error handler we have to temporarily turn off webR's other built-in error and warning capturing handlers.

Try with:

await webR.evalRVoid(`webr::global_prompt_install(FALSE)`, { withHandlers: false });

I'll reopen this to remind me to document it.

@georgestagg georgestagg reopened this Nov 22, 2023
@georgestagg georgestagg changed the title Can WebR automatically install packages in an allowed list when library(.) is called? Documentation should mention that webr::global_prompt_install() requires withHandlers: false Nov 22, 2023
@georgestagg georgestagg added docs Improvements or additions to documentation and removed question Further information is requested labels Nov 22, 2023
@georgestagg
Copy link
Member

georgestagg commented Nov 22, 2023

I've done some experimentation, and I can't seem to get this working with evalR(), though I'm sure it worked at some point. Possibly it breaks when using the PostMessage channel since that implements a limited version of the built-in R REPL.

It does seem to work when using writeConsole() and pumping .read() for output. But with that method, you can't get R object references back, just output messages.

  const webR = await new WebR();
  await webR.init();
  await webR.evalRVoid(`webr::global_prompt_install(FALSE)`, { withHandlers: false });
  await webR.writeConsole(`library(dplyr)`);
  for (;;) {
    const output = await webR.read();
    switch (output.type) {
      case 'stdout':
        console.log(output.data)
        break;
      case 'stderr':
        console.log(output.data);
        break;
      case 'prompt':
        console.log(output.data);
        break;
      default:
        console.error(`Unimplemented output type: ${output.type}`);
        console.error(output.data);
    }
  }

(https://terrific-coordinated-parrot.glitch.me/)

EDIT: yes, this is clearly not working right. Even here two invocations of library(dplyr) are needed to actually load the package.

Probably it's best to stick with your own method around shimming library() to run webr::install() for now, and I'll take a look at this when I can. It's likely we'll have to replace the global handler method with a shimming method instead.

@georgestagg georgestagg changed the title Documentation should mention that webr::global_prompt_install() requires withHandlers: false webr::global_prompt_install() not working with webR.evalR() Nov 22, 2023
@georgestagg georgestagg added bug Something isn't working and removed docs Improvements or additions to documentation labels Nov 22, 2023
@georgestagg
Copy link
Member

For completeness, something like this should allow you to shim library() for the moment,

const webR = await new WebR();
await webR.init();
await webR.evalRVoid(`
  .e <- new.env()
  .e[["library"]] <- function (pkg, ...) {
    package <- as.character(substitute(pkg))
    if (!require(package)) webr::install(package)
    base::library(package, character.only = TRUE, ...)
  }
  attach(.e, name = "library_shim", warn.conflicts = FALSE)
`);
await webR.evalR(`library(dplyr)\nprint(starwars)`);

(https://southern-parallel-form.glitch.me/)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants