Packrat with local binary repository - r

I want to use packrat on a Windows 7 machine with no internet connection.
I have downloaded all binary packages from http://cran.r-project.org/bin/windows/contrib/3.1/ into the local folder C:/xyz/CRAN_3_1.
The problem is now that
packrat::init(options=list(local.repos="C:/xyz/CRAN_3_1"))
throws a bunch of warnings and errors like
Warning: unable to access index for repository http://cran.rstudio/bin/...
Warning: unable to access index for repository http://cran.rstudio/src/...
Fetching sources for Rcpp (0.11.4) ... Failed
Package Rcpp not available in repository or locally
As it seems packrat tries to find
the binary version of Rcpp on CRAN (fails since there is no internet connection)
the source of Rcpp on CRAN (fails since there is no internet connection)
the local source of the package (fails since I only have the binaries)
What I don't understand is why packrat does not also search for the local binary package...
Question 1: I could download the source CRAN repository to get around this problem. But I would like to know from you guys whether there is an easier solution to this, i.e., whether it is possible to make packrat accept a local binary repo.
Question 2: When I create my own package myPackage with packrat enabled, will the myPackage-specific local packrat library also be included in the package? That is, assume that I give the binary myPackage zip File to one of my colleagues who does not have one of the packages that myPackage depends on (let's say Rcpp). Will Rcpp be included in myPackage when I use packrat? Or does my colleague have to install Rcpp himself?

I managed to hack around this problem. Please bear in mind that I have never used packrat before and that I do not know its "proper" behaviour. But my impression is that the hack works.
Here is how I did it:
Open your project, load packrat via library(packrat)
type fixInNamespace("snapshotImpl",ns="packrat") - a window opens - copy its content into the clipboard
Go to /yourProjDir/ and create a file snapshotImplFix.R
Copy the clipboard's content into this file ...
... but change the first line to
snapshotImplFix=function (project, available = NULL, lib.loc = libDir(project),
dry.run = FALSE, ignore.stale = FALSE, prompt = interactive(),
auto.snapshot = FALSE, verbose = TRUE, fallback.ok = FALSE,
snapshot.sources = FALSE)
Note snapshot.sources = FALSE! Save and close the file.
Create /yourProjDir/.Rprofile and add
setHook(packageEvent("packrat","onLoad"),function(...) {
source("./snapshotImplFix.R");
tmpfun=get("snapshotImpl",envir=asNamespace("packrat"));
environment(snapshotImplFix)=environment(tmpfun);
utils::assignInNamespace(x="snapshotImpl",value=snapshotImplFix,ns="packrat");})
Points 2-6 fix the problem with the snapshot.sources argument being TRUE by default (I did not find a better way to change that...)
Finally, we have to tell packrat to take our local repository. It's important that you have the right folder structure. Therefore I moved the repo from C:/xyz/CRAN_3_1 to C:/xyz/CRAN_3_1/bin/windows/contrib/3.1. Do not forget to run library(tools);write_PACKAGES("C:/xyz/CRAN_3_1/bin/windows/contrib/3.1"); if you also have to move your files.
Open yourProjDir/.Rprofile again and add at the end
local({r=getOption("repos");r["CRAN"]="file:///C:/xyz/CRAN_3_1";r["CRANextra"]=r["CRAN"];options(repos=r)})
Note the 3 / right after file! Save and exit file.
Close the project and re-open.
Now you can execute packrat::init() and it should run without errors.
It would be great if someone with more experience regarding packrat could give his/her input so that I can be sure that this hack works. Any pointers to proper solutions are highly appreciated, of course.

Related

R devtools: use local dependencies

This bounty has ended. Answers to this question are eligible for a +100 reputation bounty. Bounty grace period ends in 4 hours.
antonio wants to draw more attention to this question:
Explain what is the proper workflow when you are building two packages, where one depends on the other. What is the correct way to run devtools::check() on the depending-on package?
I want to add a local package dependency using R devtools.
The suggested way to add packages to the package DESCRIPTION file is one of the two functions use_package() and use_dev_package(), from the usethis package. The latter adds a dependency on an in-development package. The function help shows the following prototype:
use_dev_package(package, type = "Imports", remote = NULL)
where remote is
a character string to specify the remote, e.g. ‘"gitlab::jimhester/covr"’, using any syntax supported by the remotes package.
The remotes vignette shows the following
# Local
Remotes: local::/pkgs/testthat
So the command should be along these lines:
use_dev_package(foopack, type = "Imports", remote = "local::<foopack>")
However, what should be the path to the foopack. An absolute one or relative to project dir? The root package directory or the R directory with the code, or perhaps the foopack.tar.gz build?
All attempts failed for me.
Needless to say that, beyond having the local dependency properly listed in the DESCRIPTION file, I need it to be seen by the devtools build & check functions.
Edit
As regards use_dev_package(), I found a solution:
if I use devtools::check(), then the dependency appears in the search path, and use_dev_package() does not complain any more (see answer below).
However, it is still unclear to me what arguments should I use to make a development check() for the main package, in particular when the package has a vignette.
Ideally, I should be able to pass the check with local dependencies by passing cran = FALSE, but this still gives
"Package required but not available".
It seems that I have to check the local dependencies before adding them to the description file.
devtools::check("path/to/foopack")
usethis::use_dev_package("foopack", remote ="local::path/to/foopack")
The paths can be relative or absolute, and even a single colon works.
It might be worth noting that, when I build the main package, I can use the ordinary:
devtools::build()
but, for a successful check, I need to use the remote argument:
devtools::check(remote = TRUE)
I can't see a rationale for restating what is in the DESCRIPTION file, but I do not have enough expertise to say it's a bug.
Let's see what the others say in this regard.
Edit
Unfortunately, it seems that the remote argument above does not apply to vignettes. So, if I add a vignette to the package, checks fail with local packages
Until an actual solution is found, all I can do is (sadly) to ignore vignette checks:
devtools::check(remote = TRUE, vignettes = FALSE)

How to install a series of Julia packages from a file

In Python, if I install mambaforge or conda then I can make a file with extension .yml and then inside it list the name of packages I want to install alongside their specific versions. How can I do a similar way of installing packages in Julia?
I understand that if I have already installed Julia packages by addcommand in package manager, then I have a file named Project.toml which I can use to install the same packages later. However, this still does not look as good as Python's way of installing packages.
Upon further investigation I realized that to install Julia packages from an empty Prokect.tomlfile, I should add [deps]in the file followed by the name of packages I want and then give each package a uuidwhich can be found here. For example:
[deps]
Images = "916415d5-f1e6-5110-898d-aaa5f9f070e0"
After all , this is still tedious as it needs to find all those uuids.
How can I install packages in Julia the same way I described for Python?
Is there a particular reason that you want to write package names to a .yml file and then read the packages from there? After all, you can generate the Project file and add multiple dependencies automatically:
(#v1.8) pkg> generate MyProject # or whatever name you like
(#v1.8) pkg> activate MyProject
(MyProject) pkg> add Countries Crayons CSV # some example packages
(In recent versions of Julia, an installation prompt will appear if a package isn't already installed).
Speaking from experience, learning to use environments in Julia can be challenging to a new user, but rewarding! The documentation for Pkg.jl are helpful here.
If you are just assembling an environment for your own code, there is probably no need for you to manually edit Project.toml. On the other hand, if you are maintaining a package, you might wish to edit the file directly (e.g., for specifying compatability).
Maybe you can use this:
using TOML
using HTTP
using DataStructures
## Get the Registry.toml file if it already doesn't exist in the current directory
function raed_reg()
if !isfile("Registry.toml")
HTTP.download(
"https://raw.githubusercontent.com/JuliaRegistries/General/master/Registry.toml",
"Registry.toml"
)
end
reg = TOML.parsefile("Registry.toml")["packages"]
return reg
end
## Find the UUID of a specific package from the Registry.toml file
function get_uuid(pkg_name)
reg = raed_reg()
for (uuid, pkg) in reg
if pkg["name"] == pkg_name
return uuid
end
end
end
## Create a dictionary for the gotten UUIDs, by setting the name = UUID and convert it to a project.toml file
function create_project_toml(Pkgs::Vector{String})
reg = raed_reg()
pkgs_names_uuid = OrderedDict{AbstractString, AbstractString}()
pkgs_names_uuid["[deps]"] = ""
for pkg in Pkgs
_uuid = get_uuid(pkg)
pkgs_names_uuid[pkg] = _uuid
end
open("project.toml", "w") do io
TOML.print(io, pkgs_names_uuid)
end
end
## Test on the packages "ClusterAnalysis" and "EvoTrees"
create_project_toml(["ClusterAnalysis", "EvoTrees"])

How do I edit an R package from GitHub that has already been cloned?

I have an R package, created by someone else that I have been made a collaborator on, that I want to work on and develop. I've already cloned the repository to my local computer through the Create Project > Clone from GitHub route in RStudio, and since then I've been editing the scripts, but not working with it as a package. As in, I had been adding functions and working on a Shiny interface, but not following any R package development rules (loading packages directly into the .R files, not updating the NAMESPACE, using roxygen2 conventions, etc.).
Everything I've read mentions devtools::install_github, but I don't want to install and use it, I want to edit it like I've been doing. I also want it to still be connected to Git (so I can continue to commit and pull from the remote server, once my collaborators make edits). I've tried devtools::load_all() and devtools::document(), but it gives me this warning:
Error in FUN(X[[i]], ...) :
bad restore file magic number (file may be corrupted) -- no data loaded
In addition: Warning messages:
1: In readChar(con, 5L, useBytes = TRUE) :
truncating string with embedded nuls
2: file ‘file_example.rda’ has magic number 'X'
Use of save versions prior to 2 is deprecated
Do I need to delete my local copy and do something different to work with it as a package so that the functionality of roxygen2 and the NAMESPACE documentation will work correctly? Or is there an obvious reason for this error/something I'm missing about how to work with it as a package, how it is currently?
Thanks!
It looks like file_example.rda is corrupt
Can you just load it in R and check what it contains?
You could try:
tools::resaveRdaFiles( 'file_example.rda', compress='xz' )
And see if that saves it in a way that is acceptable?

RStudio Connect, Packrat, and custom packages in local repos

We have recently got RStudio Connect in my office. For our work, we have made custom packages, which we have updated amongst ourselves by opening the project and build+reloading.
I understand the only way I can get our custom packages to work within apps with RSConnect is to get up a local repo and set our options(repos) to include this.
Currently I have the following:
library(drat)
RepoAddress <- "C:/<RepoPath>" # High level path
drat::insertPackage(<sourcePackagePath>, repodir = RepoAddress)
# Add this new repo to Rs knowledge of repos.
options(repos = c(options("repos")$repos,LocalCurrent = paste0("file:",RepoAddress)))
# Install <PackageName> from the local repo :)
install.packages("<PackageName>")
Currently this works nicely and I can install my custom package from the local repo. This indicates to me that the local repo is set up correctly.
As an additional aside, I have changed the DESCRIPTION file to have an extra line saying repository:LocalCurrent.
However when I try to deploy a Shiny app or Rmd which references , I get the following error on my deploy:
Error in findLocalRepoForPkg(pkg, repos, fatal = fatal) :
No package '<PackageName> 'found in local repositories specified
I understand this is a problem with packrat being unable to find my local repos during the deploy process (I believe at a stage where it uses packrat::snapshot()).This is confusing since I would have thought packrat would use my option("repos") repos similar to install.packages. If I follow through the functions, I can see the particular point of failure is packrat:::findLocalRepoForPkg("<PackageName", repos = packrat::get_opts("local.repos")), which fails even after I define packrat::set_opts("local.repos" = c(CurrentRepo2 = paste0("file:",RepoAddress)))
If I drill into packrat:::findLocalRepoForPkg, it fails because it can't find a file/folder called: "C://". I would have thought this is guaranteed to fail, because repos follow the C://bin/windows/contrib/3.3/ structure. At no point would a repo have the structure it's looking for?
I think this last part is showing I'm materially misunderstanding something. Any guidance on configuring my repo so packrat can understand it would be great.
One should always check what options RStudio connect supports at the moment:
https://docs.rstudio.com/connect/admin/r/package-management/#private-packages
Personally I dislike all options for including local/private packages, as it defeats the purpose of having a nice easy target for deploying shiny apps. In many cases, I can't just set up local repositories in the organization because, I do not have clearance for that. It is also inconvenient that I have to email IT-support to make them manually install new packages. Overall I think RS connect is great product because it is simple, but when it comes to local packages it is really not.
I found a nice alternative/Hack to Rstudio official recommendations. I suppose thise would also work with shinyapps.io, but I have not tried. The solution goes like:
add to global.R if(!require(local_package) ) devtools::load_all("./local_package")
Write a script that copies all your source files, such that you get a shinyapp with a source directory for a local package inside, you could call the directory for ./inst/shinyconnect/ or what ever and local package would be copied to ./inst/shinyconnect/local_package
manifest.
add script ./shinyconnect/packrat_sees_these_dependencies.R to shiny folder, this will be picked up by packrat-manifest
Hack rsconnet/packrat to ignore specifically named packages when building
(1)
#start of global.R...
#load more packages for shiny
library(devtools) #need for load_all
library(shiny)
library(htmltools) #or what ever you need
#load already built local_package or for shiny connection pseudo-build on-the-fly and load
if(!require(local_package)) {
#if local_package here, just build on 2 sec with devtools::load_all()
if(file.exists("./DESCRIPTION")) load_all(".") #for local test on PC/Mac, where the shinyapp is inside the local_package
if(file.exists("./local_package/DESCRIPTION")) load_all("./local_package/") #for shiny conenct where local_package is inside shinyapp
}
library(local_package) #now local_package must load
(3)
make script loading all the dependencies of your local package. Packrat will see this. The script will never be actually be executed. Place it at ./shinyconnect/packrat_sees_these_dependencies.R
#these codelines will be recognized by packrat and package will be added to manifest
library(randomForest)
library(MASS)
library(whateverpackageyouneed)
(4) During deployment, manifest generator (packrat) will ignore the existence of any named local_package. This is an option in packrat, but rsconnect does not expose this option. A hack is to load rsconnect to memory and and modify the sub-sub-sub-function performPackratSnapshot() to allow this. In script below, I do that and deploy a shiny app.
library(rsconnect)
orig_fun = getFromNamespace("performPackratSnapshot", pos="package:rsconnect")
#packages you want include manually, and packrat to ignore
ignored_packages = c("local_package")
#highjack rsconnect
local({
assignInNamespace("performPackratSnapshot",value = function (bundleDir, verbose = FALSE) {
owd <- getwd()
on.exit(setwd(owd), add = TRUE)
setwd(bundleDir)
srp <- packrat::opts$snapshot.recommended.packages()
packrat::opts$snapshot.recommended.packages(TRUE, persist = FALSE)
packrat::opts$ignored.packages(get("ignored_packages",envir = .GlobalEnv)) #ignoreing packages mentioned here
print("ignoring following packages")
print(get("ignored_packages",envir = .GlobalEnv))
on.exit(packrat::opts$snapshot.recommended.packages(srp,persist = FALSE), add = TRUE)
packages <- c("BiocManager", "BiocInstaller")
for (package in packages) {
if (length(find.package(package, quiet = TRUE))) {
requireNamespace(package, quietly = TRUE)
break
}
}
suppressMessages(packrat::.snapshotImpl(project = bundleDir,
snapshot.sources = FALSE, fallback.ok = TRUE, verbose = FALSE,
implicit.packrat.dependency = FALSE))
TRUE
},
pos = "package:rsconnect"
)},
envir = as.environment("package:rsconnect")
)
new_fun = getFromNamespace("performPackratSnapshot", pos="package:rsconnect")
rsconnect::deployApp(appDir="./inst/shinyconnect/",appName ="shinyapp_name",logLevel = "verbose",forceUpdate = TRUE)
The problem is one of nomenclature.
I have set up a repo in the CRAN sense. It works fine and is OK. When packrat references a local repo, it is referring to a local git-style repo.
This solves why findlocalrepoforpkg doesn't look like it will work - it is designed to work with a different kind of repo.
Feel free to also reach out to support#rstudio.com
I believe the local package code path is triggered in packrat because of the missing Repository: value line in the Description file of the package. You mentioned you added this line, could you try the case-sensitive version?
That said, RStudio Connect will not be able to install the package from the RepoAddress as you've specified it (hardcoded on the Windows share). We'd recommend hosting your repo over https from a server that both your Dev environment and RStudio Connect have access to. To make this type of repo setup much easier we just released RStudio Package Manager which you (and IT!) may find a compelling alternative to manually managing releases of your internal packages via drat.

Publishing AzureML Webservice from R requires external zip utility

I want to deploy a basic trained R model as a webservice to AzureML. Similar to what is done here:
http://www.r-bloggers.com/deploying-a-car-price-model-using-r-and-azureml/
Since that post the publishWebService function in the R AzureML package was has changed it now requires me to have a workspace object as first parameter thus my R code looks as follows:
library(MASS)
library(AzureML)
PredictionModel = lm( medv ~ lstat , data = Boston )
PricePredFunktion = function(percent)
{return(predict(PredictionModel, data.frame(lstat =percent)))}
myWsID = "<my Workspace ID>"
myAuth = "<my Authorization code"
ws = workspace(myWsID, myAuth, api_endpoint = "https://studio.azureml.net/", .validate = TRUE)
# publish the R function to AzureML
PricePredService = publishWebService(
ws,
"PricePredFunktion",
"PricePredOnline",
list("lstat" = "float"),
list("mdev" = "float"),
myWsID,
myAuth
)
But every time I execute the code I get the following error:
Error in publishWebService(ws, "PricePredFunktion", "PricePredOnline", :
Requires external zip utility. Please install zip, ensure it's on your path and try again.
I tried installing programs that handle zip files (like 7zip) on my machine as well as calling the utils library in R which allows R to directly interact with zip files. But I couldn't get rid of the error.
I also found the R package code that is throwing the error, it is on line 154 on this page:
https://github.com/RevolutionAnalytics/AzureML/blob/master/R/internal.R
but it didn't help me in figuring out what to do.
Thanks in advance for any Help!
The Azure Machine Learning API requires the payload to be zipped, which is why the package insists on the zip utility being installed. (This is an unfortunate situation, and hopefully we can find a way in future to include a zip with the package.)
It is unlikely that you will ever encounter this situation on Linux, since most (all?) Linux distributions includes a zip utility.
Thus, on Windows, you have to do the following procedure once:
Install a zip utility (RTools has one and this works)
Ensure the zip is on your path
Restart R – this is important, otherwise R will not recognize the changed path
Upon completion, the litmus test is if R can see your zip. To do this, try:
Sys.which("zip")
You should get a result similar to this:
zip
"C:\\Rtools\\R-3.1\\bin\\zip.exe"
In other words, R should recognize the installation path.
On previous occasions when people told me this didn’t work, it was always because they thought they had a zip in the path, but it turned out they didn’t.
One last comment: installing 7zip may not work. The reason is that 7zip contains a utility called 7zip, but R will only look for a utility called zip.
I saw this link earlier but the additional clarification which made my code not work was
1. Address and Path of Rtools was not as straigt forward
2. You need to Reboot R
With regards to the address - always look where it was installed . I also used this code to set the path and ALWAYS ADD ZIP at the end
##Rtools.bin="C:\\Users\\User_2\\R-Portable\\Rtools\\bin"
Rtools.bin="C:\\Rtools\\bin\\zip"
sys.path = Sys.getenv("PATH")
if (Sys.which("zip") == "" ) {
system(paste("setx PATH \"", Rtools.bin, ";", sys.path, "\"", sep = ""))
}
Sys.which("zip")
you should get a return of
" C:\\RTools|\bin\zip"
From looking at Andrie's comment here: https://github.com/RevolutionAnalytics/AzureML/commit/9cf2c5c59f1f82b874dc7fdb1f9439b11ab60f40
Implies we can just download RTools and be done with it.
Download RTools from:
https://cran.r-project.org/bin/windows/Rtools/
During installation select the check box to modify the PATH
At first it didn't work. I then tried R32bit, and that seemed to work. Then R64 bit started working again. Honestly, not sure if I did something in the middle to make it work. Only takes a few minutes so worth a punt.
Try the following
-Download the Rtools file which usually contains the zip utility.
-Copy all the files in the "bin" folder of "Rtools"
-Paste them in "~/RStudio/bin/x64" folder

Resources