Beispiel #1
0
    def infer(cls, name: str, packages: Packages, channels: ListLike = None):
        """create conda_env_tracker environment by inferring to existing conda environment"""
        if name == "base":
            raise CondaEnvTrackerCondaError(
                "Environment can not be created using default name base"
            )

        if name not in get_all_existing_environment():
            raise CondaEnvTrackerCondaError(
                f"Environment {name} can not be inferred, does not exist"
            )

        existing_packages = get_dependencies(name=name)
        if "r-base" in existing_packages["conda"]:
            existing_r_packages = get_r_dependencies(name=name)
        else:
            existing_r_packages = {}

        user_packages = {"conda": Packages(), "pip": Packages(), "r": Packages()}
        for package in packages:
            if package.name in existing_packages.get("conda", Packages()):
                user_packages["conda"].append(package)
            elif package.name in existing_packages.get("pip", Packages()):
                user_packages["pip"].append(package)
            elif package.name in existing_r_packages:
                raise RError(
                    "Cannot infer R packages, must run follow-up R install command.\n"
                    f"Found '{package.name}' in installed R packages {existing_r_packages}."
                )
            else:
                raise CondaEnvTrackerCondaError(
                    f"Environment {name} does not have {package.spec} installed"
                )

        conda_create_cmd = get_conda_create_command(
            name, user_packages["conda"], channels
        )

        specs = Actions.get_package_specs(
            packages=user_packages["conda"], dependencies=existing_packages["conda"]
        )
        history = History(
            name=name,
            channels=Channels(channels),
            packages=HistoryPackages.create(user_packages["conda"]),
            logs=Logs.create(conda_create_cmd),
            actions=Actions.create(name=name, specs=specs, channels=Channels(channels)),
            debug=Debug.create(name=name),
        )

        env = cls(name=name, history=history)
        if user_packages["pip"]:
            handler = PipHandler(env=env)
            handler.update_history_install(packages=user_packages["pip"])
            env = handler.env
        env.export()

        return env
Beispiel #2
0
    def create(
        cls,
        name: str,
        packages: Packages,
        channels: ListLike = None,
        yes: bool = False,
        strict_channel_priority: bool = True,
    ):
        """Creating a conda environment from a list of packages."""
        if name == "base":
            raise CondaEnvTrackerCondaError(
                "Environment can not be created using default name base"
            )

        if name in get_all_existing_environment():
            raise CondaEnvTrackerCondaError(f"Environment {name} already exist")
        logger.debug(f"creating conda env {name}")

        conda_create(
            name=name,
            packages=packages,
            channels=channels,
            yes=yes,
            strict_channel_priority=strict_channel_priority,
        )
        create_cmd = get_conda_create_command(
            name=name,
            packages=packages,
            channels=channels,
            strict_channel_priority=strict_channel_priority,
        )
        specs = Actions.get_package_specs(
            packages=packages, dependencies=get_dependencies(name=name)["conda"]
        )

        if not channels:
            channels = get_conda_channels()

        history = History(
            name=name,
            channels=Channels(channels),
            packages=HistoryPackages.create(packages),
            logs=Logs.create(create_cmd),
            actions=Actions.create(
                name=name,
                specs=specs,
                channels=Channels(channels),
                strict_channel_priority=strict_channel_priority,
            ),
            debug=Debug.create(name=name),
        )
        env = cls(name=name, history=history)
        env.export()

        return env
Beispiel #3
0
def get_dependencies(name: str) -> dict:
    """Get the information about pip and conda packages in the environment using `conda list`.

    Package information includes: name and version
    """
    completed_process = subprocess.run(
        f"conda list --name {name}",
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        shell=True,
        encoding="UTF-8",
    )
    if completed_process.returncode != 0:
        error_message = completed_process.stderr.strip()
        raise CondaEnvTrackerCondaError(error_message)
    lines = completed_process.stdout.strip().split("\n")
    dependencies = {"conda": {}}
    for line in lines:
        if not line.startswith("#"):
            dep = line.strip().split()
            name = dep[0]
            spec = name
            version = dep[1]
            if dep[-1] in ["pip", "pypi"]:
                dependencies["pip"] = dependencies.get("pip", {})
                dependencies["pip"][name] = Package(name, spec, version)
            else:
                build = dep[2]
                dependencies["conda"][name] = Package(name, spec, version,
                                                      build)

    return dependencies
Beispiel #4
0
def delete_conda_environment(name: str) -> None:
    """Delete conda environment"""
    if os.environ["CONDA_DEFAULT_ENV"] == name:
        raise CondaEnvTrackerCondaError(
            f'Must run "conda deactivate" before removing or rebuilding the {name} environment.'
        )
    subprocess.run(f"conda env remove -y --name {name}", shell=True)
Beispiel #5
0
def _get_env_file(env_dir: Path) -> Path:
    """Get the environment file. This file only contains packages the 
    user has specifically asked for and does not contain dependencies."""
    env_file = env_dir / "conda-env.yaml"
    if env_file.exists():
        return env_file
    raise CondaEnvTrackerCondaError(
        f"No environment file to update from in {env_dir}.\n"
        "Someone may need to push to this remote or recover the lost file in some other way."
    )
Beispiel #6
0
def init() -> str:
    """Check conda version."""
    completed_process = subprocess.run(
        "conda --version",
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        shell=True,
        encoding="UTF-8",
    )
    process_code = completed_process.returncode
    if process_code == 0:
        conda_version = completed_process.stdout.rstrip().split(" ")[1]
    else:
        raise CondaEnvTrackerCondaError(
            "Error checking conda version. Maybe you haven't installed anaconda/miniconda?"
            f"\nError: {completed_process.stderr}")
    if conda_version < MINIMUM_CONDA_VERSION:
        raise CondaEnvTrackerCondaError(
            f"Need conda>={MINIMUM_CONDA_VERSION}, but found conda={conda_version}."
            ' Please run "conda update -n base conda".')
    logger.info(f"Using conda version {conda_version}")
    return conda_version
Beispiel #7
0
def get_conda_bin_path() -> Path:
    """Find the path to the conda binary."""
    conda_exe_path = os.environ.get("CONDA_EXE")
    if conda_exe_path:
        return Path(conda_exe_path).parent
    completed_process = subprocess.run(
        "which conda",
        shell=True,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        encoding="UTF-8",
    )
    process_code = completed_process.returncode
    if process_code != 0:
        raise CondaEnvTrackerCondaError(
            "CondaEnvTracker requires an anaconda/miniconda install")
    return Path(completed_process.stdout.strip()).parent
Beispiel #8
0
    def create(
        cls,
        name: str,
        packages: Packages,
        channels: ListLike = None,
        yes: bool = False,
        strict_channel_priority: bool = True,
    ):
        """Creating a conda environment from a list of packages."""
        if name == "base":
            raise CondaEnvTrackerCondaError(
                "Environment can not be created using default name base"
            )

        if name in get_all_existing_environment():
            message = (
                f"This environment {name} already exists. Would you like to replace it"
            )
            if prompt_yes_no(prompt_msg=message, default=False):
                delete_conda_environment(name=name)
                local_io = EnvIO(env_directory=USER_ENVS_DIR / name)
                if local_io.env_dir.exists():
                    local_io.delete_all()
            else:
                raise CondaEnvTrackerCondaError(f"Environment {name} already exists")
        logger.debug(f"creating conda env {name}")

        conda_create(
            name=name,
            packages=packages,
            channels=channels,
            yes=yes,
            strict_channel_priority=strict_channel_priority,
        )
        create_cmd = get_conda_create_command(
            name=name,
            packages=packages,
            channels=channels,
            strict_channel_priority=strict_channel_priority,
        )
        specs = Actions.get_package_specs(
            packages=packages, dependencies=get_dependencies(name=name)["conda"]
        )

        if not channels:
            channels = get_conda_channels()

        dependencies = get_dependencies(name=name)

        history = History.create(
            name=name,
            channels=Channels(channels),
            packages=PackageRevision.create(packages, dependencies=dependencies),
            logs=Logs(create_cmd),
            actions=Actions.create(
                name=name,
                specs=specs,
                channels=Channels(channels),
                strict_channel_priority=strict_channel_priority,
            ),
            diff=Diff.create(packages=packages, dependencies=dependencies),
            debug=Debug.create(name=name),
        )
        env = cls(name=name, history=history, dependencies=dependencies)
        env.export()

        return env