trinker / pacman

A package management tools for R
311 stars 37 forks source link

cannot using pacman with shinyapps.io deploment #82

Open xhdong-umd opened 7 years ago

xhdong-umd commented 7 years ago

I like to use pacman because when I shared my script to others, they can run script to install/load in one time, instead of install packages manually.

However this doesn't work with shiny apps deployed to shinyapps.io. I have to change my usage of

if (!require("pacman")) install.packages("pacman")
pacman::p_load(shiny, shinydashboard, DT, ctmm, ggplot2, scales, gridExtra, data.table, markdown)

in to a series library calls.

The error log in shinyapps.io is:


2017-02-10T19:01:00.585072+00:00 shinyapps[154758]: rmarkdown version: NA
2017-02-10T19:01:00.585106+00:00 shinyapps[154758]: knitr version: NA
2017-02-10T19:01:00.827415+00:00 shinyapps[154758]: 
2017-02-10T19:01:00.585146+00:00 shinyapps[154758]: jsonlite version: 1.2
2017-02-10T19:01:00.585220+00:00 shinyapps[154758]: htmltools version: 0.3.5
2017-02-10T19:01:00.827418+00:00 shinyapps[154758]: Starting R with process ID: '36'
2017-02-10T19:01:00.844833+00:00 shinyapps[154758]: 
2017-02-10T19:01:00.844836+00:00 shinyapps[154758]: Listening on http://0.0.0.0:42672
2017-02-10T19:01:00.907832+00:00 shinyapps[154758]: Loading required package: pacman
2017-02-10T19:01:00.933056+00:00 shinyapps[154758]: Installing package into ‘/usr/local/lib/R/site-library’
2017-02-10T19:01:00.933063+00:00 shinyapps[154758]: (as ‘lib’ is unspecified)
2017-02-10T19:01:00.972008+00:00 shinyapps[154758]: Installing package into ‘/usr/local/lib/R/site-library’
2017-02-10T19:01:00.972012+00:00 shinyapps[154758]: (as ‘lib’ is unspecified)
2017-02-10T19:01:00.972422+00:00 shinyapps[154758]: Warning in install.packages("BiocInstaller", repos = a["BioCsoft", "URL"]) :
2017-02-10T19:01:00.972424+00:00 shinyapps[154758]:   'lib = "/usr/local/lib/R/site-library"' is not writable
2017-02-10T19:01:00.973770+00:00 shinyapps[154758]: Warning: Error in install.packages: unable to install packages
2017-02-10T19:01:00.983000+00:00 shinyapps[154758]: Stack trace (innermost first):
2017-02-10T19:01:00.983004+00:00 shinyapps[154758]:     72: install.packages
2017-02-10T19:01:00.983005+00:00 shinyapps[154758]:     71: eval
2017-02-10T19:01:00.983006+00:00 shinyapps[154758]:     70: eval
2017-02-10T19:01:00.983006+00:00 shinyapps[154758]:     69: eval
2017-02-10T19:01:00.983007+00:00 shinyapps[154758]:     68: eval
2017-02-10T19:01:00.983007+00:00 shinyapps[154758]:     67: eval.parent
2017-02-10T19:01:00.983007+00:00 shinyapps[154758]:     66: local
2017-02-10T19:01:00.983008+00:00 shinyapps[154758]:     65: eval
2017-02-10T19:01:00.983009+00:00 shinyapps[154758]:     63: withVisible
2017-02-10T19:01:00.983009+00:00 shinyapps[154758]:     62: source
2017-02-10T19:01:00.983009+00:00 shinyapps[154758]:     61: value[[3L]]
2017-02-10T19:01:00.983010+00:00 shinyapps[154758]:     60: tryCatchOne
2017-02-10T19:01:00.983010+00:00 shinyapps[154758]:     59: tryCatchList
2017-02-10T19:01:00.983010+00:00 shinyapps[154758]:     58: tryCatch
2017-02-10T19:01:00.983011+00:00 shinyapps[154758]:     57: p_install
2017-02-10T19:01:00.983011+00:00 shinyapps[154758]:     56: FUN
2017-02-10T19:01:00.983011+00:00 shinyapps[154758]:     55: lapply
2017-02-10T19:01:00.983008+00:00 shinyapps[154758]:     64: eval
2017-02-10T19:01:00.983012+00:00 shinyapps[154758]:     13: runApp
2017-02-10T19:01:00.983013+00:00 shinyapps[154758]:     12: fn
2017-02-10T19:01:00.983013+00:00 shinyapps[154758]:     11: doTryCatch
2017-02-10T19:01:00.983013+00:00 shinyapps[154758]:     10: tryCatchOne
2017-02-10T19:01:00.983014+00:00 shinyapps[154758]:      9: tryCatchList
2017-02-10T19:01:00.983012+00:00 shinyapps[154758]:     53: pacman::p_load
2017-02-10T19:01:00.983015+00:00 shinyapps[154758]:      5: eval
2017-02-10T19:01:00.983012+00:00 shinyapps[154758]:     54: sapply
2017-02-10T19:01:00.983016+00:00 shinyapps[154758]:      3: eval
2017-02-10T19:01:00.983016+00:00 shinyapps[154758]:      2: eval.parent
2017-02-10T19:01:00.983016+00:00 shinyapps[154758]:      1: local
2017-02-10T19:01:00.983369+00:00 shinyapps[154758]: Error : unable to install packages
2017-02-10T19:01:00.983014+00:00 shinyapps[154758]:      7: connect$retry
2017-02-10T19:01:00.983015+00:00 shinyapps[154758]:      6: eval
2017-02-10T19:01:00.983014+00:00 shinyapps[154758]:      8: tryCatch
2017-02-10T19:01:00.983015+00:00 shinyapps[154758]:      4: eval

Is it possible to fix this? Thanks!

trinker commented 7 years ago

Not on my end. I believe this is on Rstudio/shiny people. I'm guessing the parser looks for library/require calls when bundling :-(

You can open a request there.

xhdong-umd commented 7 years ago

Yes I guess it should be their problem. Just wanted to know if you can guess something from the log error. Looks to me that it tried to install to system lib folder instead of user folder. The shinyapps should have "user folder" but probably in different names/settings.

Reported the issue in rstudio. Thanks!

xhdong-umd commented 7 years ago

Upon further reading documents, it seemed that they only check library call to install packages. And there is a explicit install.package call in my pacman script which cause problem.

I'm not sure if there is a perfect solution to support pacman usage in shiny deployment, and keep the script usable in sharing to others.

trinker commented 7 years ago

I think at the very least we can do a parser that converts between multiple library calls and p_load is useful. This could be wrapped with an if else

trinker commented 7 years ago

I have the following initial code for converting p_load to a series of library calls. @Dasonk thoughts on inclusion?

p_convert <- function(...){
    packages <- as.character(unlist(as.list(match.call()[[2]])[-1]))
    clipr::write_clip(paste(paste0('library(', packages, ')'), collapse = "\n"))
    cat(paste(paste0('library(', packages, ')'), collapse = "\n"), "\n")
}

p_convert(p_load(tidyverse, maps, maptools, rgeos, ggmap, units, albersusa))
library(tidyverse)
library(maps)
library(maptools)
library(rgeos)
library(ggmap)
library(units)
library(albersusa) 
xhdong-umd commented 7 years ago

@trinker Thanks for the update! Though I'm not sure about 2 things:

  1. what's the purpose of writing library calls into clipboard? I'm not aware of this usage.

  2. If shinyapps is going to scan r script in source code level, maybe they will not detect the conversion made by p_convert.

This problem really should be solved in shiny side, unless we generate another source file after parsing.

xhdong-umd commented 7 years ago

@trinker After tracking in source code of rsconnect I found the code responsible for parsing libraries is in packrat.

We should add pacman support there and it will be supported by packrat.

trinker commented 7 years ago

@xhdong-umd Yeah this was more of an attempt on pacman's end to convert pacman calls to shiny ap friendly library calls. This proposal is a manual solution that would replace the pacman calls or use an if else. The clipr dependency is just to copy to the clipboard for easy pasting. This solution will not be picked up by the shiny app build just by wrapping p_load, it was intended to be a manual "in the meantime"approach.

The real solution would be for packrat or what every shiny.io dependency, to detect p_load

xhdong-umd commented 7 years ago

@trinker Do you mean user write p_convert with list of libraries in script, then execute that line and convert it into a series library calls, paste them into code to replace the p_convert line? If this is the case, p_load can install packages if not available, can p_convert do the same in this usage?

I'm thinking to add a pull request for pacman support in packrat but don't have time now.

trinker commented 7 years ago

No, all p_convert does is grab the packages and pump them to the clipboard in a library (non-pacman) fashion that needs to be pasted into the script. I believe one can have both pacman (first) and library calls int he same script so long as they are redundant (you're not relying on pacman calls for the app to be built with the correct dependencies.

That being said..that were're having to go back and forth on this to this extent tells me that p_convert is a bad idea that really is a band-aid not a solution and not intuitive. The real solution is to:

add a pull request for pacman support in packrat but don't have time now.

When you have time (which would be appreciated)

xhdong-umd commented 7 years ago

OK Now I understand the idea. Though user need to keep the two versions in sync when he made some changes. I'm looking at packrat code now.

xhdong-umd commented 7 years ago

@trinker I created a pull request in packrat. The problem should be solved. I have tested with my app and everything works now. There are some known limitation of syntax supported. Only p_load is supported because only this usage is useful for me. p_load_gh have some problems installing some github repo so I don't use it.

arguments that saved in variable.

    op <- TRUE
    pacman::p_load(shinyjs, install = op)
    pkgs <- c("dplyr", "tibble")
    pacman::p_load(pkgs, character.only = TRUE)

similar usage for library cannot be detected with original packrat either. I assume this kind of usage is rare and that means some more dynamical package loading, which is not suitable for shiny deployment.

    pkg <- "ggmap"
    library(pkg, character.only = TRUE)
trinker commented 7 years ago

Thanks for doing that. Let's leave this open until they accept the pull request

xhdong-umd commented 7 years ago

I found p_load_gh works but decided not to add direct support for it because the github repo string could be quite complicated. Instead user just need to load that package in p_load again, which will make sure the packages be picked up by packrat, and there is no negative impact of this.