datasnakes / renv

Creating virtual environments for R.
MIT License
17 stars 0 forks source link

Make alternate create() method (Linux only). #2

Open grabear opened 6 years ago

grabear commented 6 years ago

The create method is the workhorse of this class. It uses all of the other methods to create the virtual environment. Below is the python version:

def create(self, env_dir):
        """
        Create a virtual environment in a directory.
        :param env_dir: The target directory to create an environment in.
        """
        env_dir = os.path.abspath(env_dir)
        context = self.ensure_directories(env_dir)
        # See issue 24875. We need system_site_packages to be False
        # until after pip is installed.
        true_system_site_packages = self.system_site_packages
        self.system_site_packages = False
        self.create_configuration(context)
        self.setup_python(context)
        if self.with_pip:
            self._setup_pip(context)
        if not self.upgrade:
            self.setup_scripts(context)
            self.post_setup(context)
        if true_system_site_packages:
            # We had set it to False before, now
            # restore it and rewrite the configuration
            self.system_site_packages = True
            self.create_configuration(context)
grabear commented 6 years ago

Current (6-6-2018) #TODO List

image

grabear commented 5 years ago

@grabear's Feb 2019 renv Overview

For my own sake and for everyone elses, I'm creating an overview of this repository. I'm doing it in this issue because it is an EPIC and it encompasses the primary bit of control flow for renv (e.g. the create() method).

The create method ties all of our programming together. Just taking a look at the CLI module will reveal that:

@click.command()
@click.option('--r_path', '-r', default=None,
              help="Provide the root of the directory tree where R is installed.  This would be R's installation "
                   "directory when using ./configure --prefix=<r_path>.")
@click.option('--env_name', '-n', default=None,
              help="Name of the environment.")
@click.option('--env_dir', '-d', default=None,
              help="A directory for creating the environment in.")
@click.option('--binpath', '-b',
              help="Provide the bin directory if R was installed when using ./configure --bindir=<binpath>.")
@click.option('--libpath', '-l',
              help="Provide the lib directory if R was installed when using ./configure --libdir=<libpath>.")
@click.option('--includepath', '-i',
              help="Provide the include directory if R was installed when using ./configure --includedir=<includepath>.")
@click.option('--system_site_packages', '-sp', type=bool, default=False,
              help="This determines whether or not the R_LIBS_USER environment variable utilizes the "
                   "original R's package library as a secondary source for loading packages.")
@click.option('--recommended_packages', '-rp', type=bool, default=True,
              help="This determines wheather or not the recommended packages are installed in the"
                   "R environment along with the base packages.  In most cases it's best to keep the"
                   "default value.")
@click.option('--clear', type=bool, default=False,
              help="Deletes the contents of the environment directory if it already exists, "
                   "before environment creation.")
@click.option('--upgrade', '-u', type=bool, default=False,
              help="Upgrades the environment directory to use this version of R.")
@click.option('--prompt', '-p', default=None,
              help="Provide an alternative prompt prefix for this environment.")
def renv(r_path, env_name, env_dir, binpath, libpath,
         includepath, system_site_packages,
         recommended_packages, clear, upgrade, prompt):

    if os.name == 'nt':
        use_symlinks = False
    else:
        use_symlinks = True

    builder = RenvBuilder(r_path=r_path, r_bin_path=binpath, r_lib_path=libpath, r_include_path=includepath,
                          system_site_packages=system_site_packages,
                          recommended_packages=recommended_packages,
                          clear=clear, symlinks=use_symlinks, upgrade=upgrade,
                          prompt=prompt)

    builder.create(env_dir, env_name)

Here's what the create() function looks like:

    def create(self, env_dir, env_name=None):
        """
        Create a virtual environment in a directory.
        :param env_dir: The target directory to create an environment in.
        """
        if env_dir:
            env_dir = os.path.abspath(env_dir)
        else:
            env_dir = utils.get_beri_path()
            if env_name:
                env_dir = os.path.join(env_dir, env_name)
            else:
                Exception("Please provide the environment name.")

        context = self.ensure_directories(env_dir)
        # TODO-ROB: pip will eventually be beRi
        # See issue 24875. We need system_site_packages to be False
        # until after pip is installed.
        true_system_site_packages = self.system_site_packages
        self.system_site_packages = False
        context.config_dict = self.create_configuration(context)
        # self.setup_r(context)
        # TODO-ROB: pip will eventually be beRi
        # if self.with_pip:
        #     self._setup_pip(context)
        if not self.upgrade:
            self.install_scripts(context)
            self.setup_r(context)
            self.post_setup(context)
        if true_system_site_packages:
            # We had set it to False before, now
            # restore it and rewrite the configuration
            self.setup_r(context)
            self.system_site_packages = True
            self.create_configuration(context)

        print("\nEnvironment created in " + env_dir + "\n")

This is what's going on:

# This function makes directories and creates a types.SimpleNamespace
# to keep up with those directory contexts
context = self.ensure_directories(env_dir)

# The next function uses a YAML config file (default or user) to get custom 
# configuration options
context.config = self.create_configuration(context)

# This function uses cookiecutter to install the proper virtual environment
# scripts into the environment (activate/deactivate) using the proper context.
self.install_scripts(context)

# This function sets up an R executable in the virtual environment
self.setup_r(context)

There are some other big picture things going on here, but that's basically all that's happening. Some of the funcitons are doing the configuration using YAML and cookiecutter, and the others are using that configuration to create the environment.

It seems like we have most of this hashed out, so we just need to start testing what we have on a Linux OS to debug everything.