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

Possible to "create" renvs at a path other than home directory? #1

Closed
colearendt opened this issue Jan 3, 2019 · 7 comments
Closed

Comments

@colearendt
Copy link
Member

I feel like I am seeing some type of weirdness with renvs that are tried with a path.

library(reprex)
renv::init()
#> * Virtual environment 'reprex548277d89f6' activated -- please restart the R session.
renv::activate()
#> * Virtual environment 'reprex548277d89f6' activated -- please restart the R session.
text <- "blahblah2"
renv::create(paste0("/", text))
system("ls ~/.renv/environment", intern = TRUE)
#> [1] "blah" "tmp"

system("ls ./", intern = TRUE)
#> [1] "renv"                   "reprex_reprex.R"       
#> [3] "reprex_reprex.spin.R"   "reprex_reprex.spin.Rmd"

renv::deactivate()
#> * Virtual environment deactivated -- please restart the R session.
renv::create(paste0("/tmp/", text))
system("ls ~/.renv/environment", intern = TRUE)
#> [1] "blah" "tmp"
system("ls ~/.renv/environment/tmp/", intern = TRUE)
#> [1] "blah"
renv::create(paste0("./", text))
#> Error: Local virtual environment './blahblah2' already exists.
system("ls ~/.renv/environment", intern = TRUE)
#> [1] "blah" "tmp"

system("ls ./", intern = TRUE)
#> [1] "renv"                   "reprex_reprex.R"       
#> [3] "reprex_reprex.spin.R"   "reprex_reprex.spin.Rmd"

Created on 2019-01-03 by the reprex package (v0.2.1)

I think this relates to my preferences in virtualenv 😄

Not sure if renv::init() is the only way you can get a renv within a project, and whether any project would ever be justified in having more than one renv locally.

The other use case to wonder about here is whether you could put renvs or the cache at a shared location. This is something that I know some users were interested in for packrat.

@kevinushey
Copy link
Collaborator

This isn't possible (yet?). Virtual environments are either global, or project-local.

Project-local environments will be created with renv::create(..., local = TRUE) but it looks like this isn't working as expected just yet.

The cache location is configurable with the RENV_PATHS_CACHE environment variable. I haven't yet thought about the best way for users to declaratively set this if e.g. they want this set for all users on a system, or specific projects, and so on. (Maybe just in .Renvirons? Still thinking about it)

@kevinushey
Copy link
Collaborator

kevinushey commented Jan 19, 2019

I've added some code to allow for absolute paths to environments, but need to think this through a bit more.

In Python, a virtual environment is a directory of 'stuff' -- including a Python binary (usually as a symlink), as well as related utilities. Normally, the intention is that one 'activates' a Python virtual environment by running the Python binary in that virtual environment.

In renv, the files within ~/.renv/environment are really just blueprints for creating / activating R virtual environments. They aren't self-contained directories on their own. That is, when running in an R session, calling

renv::activate("environment")

you're writing the infrastructure to load that environment into the current project, so that the associated environment can be automatically loaded. This is opposed to the Python model, when that infrastructure lives within the virtual environment itself.

Just to drive the point home, let's compare the layout for a Python virtual environment:

kevin@zordon:~/.virtualenvs
$ tree -L 2 testenv
testenv
├── bin
│   ├── activate
│   ├── activate.csh
│   ├── activate.fish
│   ├── activate_this.py
│   ├── easy_install
│   ├── easy_install-2.7
│   ├── pip
│   ├── pip2
│   ├── pip2.7
│   ├── python -> python2.7
│   ├── python-config
│   ├── python2 -> python2.7
│   ├── python2.7
│   └── wheel
├── include
│   └── python2.7 -> /usr/local/Cellar/python@2/2.7.15_2/Frameworks/Python.framework/Versions/2.7/include/python2.7
├── lib
│   └── python2.7
└── pip-selfcheck.json

And for an renv:

$ tree renv
renv
├── activate.R
├── activate.dcf
└── manifest
    └── 2019-01-19
        └── 2019-01-19T10-16-17PST

With the actual pieces of the virtual environment (the R library) living in ~/.renv (by default).

The intention is that R sessions launched in the project directory will use the .Rprofile to source activate.R on startup. activate.dcf is the metadata needed to initialize things as needed.

I think one nice thing about the renv approach is that the infrastructure is minimal, and can easily be version controlled alongside the project, whereas I'm less sure about how version control + Python virtual environments are handled.

It sounds like users just call pip freeze and pip install -r as required? But that doesn't really encode the state of the virtual environment; just the Python packages that were installed. The onus is still on the user in that case to create a virtual environment, activate it, and then install packages into that environment.

@kevinushey
Copy link
Collaborator

All that said -- a virtual environment should probably just be a directory; I'm already confusing myself trying to explain the semantics here so it could probably be simplified.

@colearendt
Copy link
Member Author

colearendt commented Jan 23, 2019

Ahh I see. Very interesting. I think my desire for arbitrary directories is more a holdover from the Python virtualenv way of doing things, where the naming of the environment is (and probably should be) arbitrary lest there are naming collisions across projects. For instance, I am not a huge fan of Python virtualenv "home directory" behavior where you have to name the environment for storage at the home directory level and naming collisions are possible. I much prefer to name the project at the project level, with some type of state stored at the home directory or some other location for optimization.

At very least, I think the exercise of simplifying / explaining the semantics will be valuable, as users will need to work with many of these varied constructs across languages.

@kevinushey
Copy link
Collaborator

We've decided to eschew the concepts of 'global' vs. 'local' virtual environments. Instead, we just have the Packrat default baseline of a project-local library.

@brshallo
Copy link

What code did @kevinushey add?

I've added some code to allow for absolute paths to environments.

To point a project to another projects environment locally, I add the line to the ".Rprofile" : renv::load("dir_with_renv") but wasn't sure if there was another way I should be doing this...?

@kevinushey
Copy link
Collaborator

The conversation in this issue is now outdated -- the way renv works has been re-architected since then. Previously, we were considering decoupling projects and environments, so projects could 'bind' to arbitrary environments; now, each project gets their own environment that is normally automatically activated through a project .Rprofile.

What you're doing is exactly what we would suggest with the current architecture :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants