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

Add option to install local source packages #34

Closed
trybik opened this issue Dec 6, 2017 · 8 comments
Closed

Add option to install local source packages #34

trybik opened this issue Dec 6, 2017 · 8 comments

Comments

@trybik
Copy link
Contributor

trybik commented Dec 6, 2017

IMVHO it would be nice to have on top of pkgs and remotes parameters of create_app, an additional parameter, say sources, which would execute:

for (i in seq_along(sources)) {
    .... # check here or earlier if the ".tar.gz" source package file is avail in the app folder
    install.packages(sources[i], type="source", repos = NULL)
}

This would allow to easily add package dependencies outside of the CRAN or GitHub, or to install older versions of CRAN packages.

@Dripdrop12
Copy link
Member

You must have read my mind! @willbradley is working on a way to support older pkgs with a named list. For example, create_app(pgs = c("dplyr" = 1.0, "shiny", "plotly" = 0.9)). Would that cover your use case?

@trybik
Copy link
Contributor Author

trybik commented Dec 6, 2017

No, I really need the more general "local" packages installation. The older versions of CRAN packages would be just a side-bonus. Here is what I've ended up with ATM:

  1. In the "package_manager.R" file:
    ...
    # local packages and version hard-coded ATM 
    local.pkgs = c("pkgname")
    local.versions = c("N.M")
    # Load functions to ensure software dependencies
    source("utils/ensure.R")
    ...
    ._ <- lapply(pkgs, ensure, repo = config$pkgs$cran)
    setWinProgressBar(pb, 0, label = "Ensuring Local package dependencies ...")
    ._ <- mapply(ensure_local, local.pkgs, local.versions)
     if (remotes[1] != "none") {
    ....
  1. In the "ensure.R":
    ensure_local <- function(pkg, min.version="0.0", lib.path = file.path(appwd, "local"), load = TRUE) {
      setWinProgressBar(pb,
        value = grep(paste0("\\b", pkg, "\\b"), local.pkgs) / (length(local.pkgs) + 1),
        label = sprintf("Loading - %s...", pkg))
      if (!(pkg %in% row.names(installed.packages())) || (packageVersion(pkg) < min.version)) {
        inst = devtools::install(file.path(lib.path, pkg))
      }
      if (load) {
        library(pkg, character.only = TRUE)
      }
    }

And I keep the local packages as sub-folders in the "app/local" folder (unpacked - had some issues with ".tar.gz" for my package).

@Dripdrop12
Copy link
Member

Would you like us to support this with something like:

create_app("myapp", "app",
    pkgs = c(shiny = "1.0", dplyr = "0.9.1"),
    remotes = c("ficonsulting/RInno"),
    locals = c(pkgname = list(
        version = "0.0.1", 
        path = "local")
    )
)

We can have that information persist into package_manager.R and call ensure_local as you laid out above.

@trybik
Copy link
Contributor Author

trybik commented Dec 11, 2017

That would be perfect.

NB: would be nice to support usual versioning relations e.g. ">= 1.2", "== 1.2", like this: eval(parse(text=paste(paste0("packageVersion(\"", pkgname, "\")"), version))) (+/- prefixing version with "==" if none or only "=" rel. given and error for non-supported rels). Same piece of code could be used for #24 .

Thank you - I appreciate your responsiveness and openness.

@Dripdrop12 Dripdrop12 added this to To Do in RInno Dec 14, 2017
@Dripdrop12 Dripdrop12 moved this from To Do to In progress in RInno Dec 14, 2017
@Dripdrop12
Copy link
Member

@trybik here is what we have in dev:

ensure_local <- function(pkg, pkg_name, lib.path) {
  setWinProgressBar(pb,
    value = grep(paste0("\\b", pkg, "\\b"), locals) / (length(locals) + 1),
    label = sprintf("Loading - %s...", pkg_name))
  if (!(pkg_name %in% row.names(installed.packages())) || (utils::packageVersion(pkg_name) != pkg)) {
    install.packages(
      list.files(lib.path, pattern = pkg_name, full.names = TRUE),
      repos = NULL,
      type = "source")
  }
  library(pkg_name, character.only = TRUE)
}

I'm not sure we want to force users to add <, >, <=, and/or == because they are effectively the same or incorrect relative to != a given version.

  • == should never be used because it will just re-install the package if it is the same as the package that is already installed, and do nothing otherwise. Infinite re-installs for nothing.
  • <, > isolate the upper and lower bounds of what is reinstalled, but you will not know what version people are actually using because there are a range of acceptable versions.
  • >= and <= have all these issues combined into one hot mess.

Do you have a good use case for supporting these options? Otherwise, I think ensure_local is a good solution here. What are your thoughts?

@trybik
Copy link
Contributor Author

trybik commented Dec 20, 2017

I don't really follow, incl. what is pkg in (utils::packageVersion(pkg_name) != pkg)?

Reg. the exact/min/max versions, there are two elements to consider here, which reg. not only local packages, but also : 1. optional versions specification (think pip requirements file), 2. implementation with actual equality and inequality operators using packageVersion. I believe you write about 2., which is a technical nuisance, once 1. is settled (e.g. in my code snippet "<" R operator is used to implement min. version specification as would be done with ">=").

I think supporting "==", ">=" operators is standard across many tools. One assumes backward compatibility and does not need to know which version is actually installed. Note: "<=" could be useful to specify version at which package lost its required backward compatibility, but in practice, e.g. in pip requirements files, one uses then just "==" with the last version that supports used API. In my case, an API function required for the app appeared only in version "1.2" of the package, which is ATM only available directly from the author, whereas current CRAN version is "1.1". In turn, specifying either "==1.2" or ">=1.2" would make me happy.

@trybik
Copy link
Contributor Author

trybik commented Dec 20, 2017

Closer example of versioning specification: R DESCRIPTION file, see "Versioning" section.

@Dripdrop12
Copy link
Member

Hadley references are pretty hard to contend with @trybik. Well played sir. You'll get your eval(parse(text = "nonsense")) after all ;)

@Dripdrop12 Dripdrop12 self-assigned this Dec 21, 2017
RInno automation moved this from In progress to Done Dec 22, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
RInno
  
Done
Development

No branches or pull requests

3 participants