def test_prompt_yes_no(mocker, return_values):
    patch = mocker.patch("conda_env_tracker.utils.input",
                         side_effect=return_values)
    if return_values[-1] in ["n", "no"]:
        assert not prompt_yes_no(prompt_msg="")
    else:
        assert prompt_yes_no(prompt_msg="")
    assert len(patch.call_args_list) == len(return_values)
Exemple #2
0
def _ask_user_to_sync(name: str, yes: bool = False):
    """If the user is updating the environment and using the auto functionality then ask if they want to sync."""
    if (
        not yes
        and os.environ.get("CET_AUTO") == "0"
        and _remote_dir_is_set(name=name)
        and prompt_yes_no(f"Conda-env-tracker sync changes to '{name}' environment")
    ):
        sync(name=name, yes=True)
Exemple #3
0
 def remove(self, yes=False) -> None:
     """Remove the environment and history."""
     if yes or prompt_yes_no(
         f"Are you sure you want to remove the {self.name} environment",
         default=False,
     ):
         delete_conda_environment(name=self.name)
         try:
             remote_io = EnvIO(self.local_io.get_remote_dir())
         except CondaEnvTrackerRemoteError:
             remote_io = None
         self.local_io.delete_all()
         if remote_io and (
             yes
             or prompt_yes_no(
                 prompt_msg=f"Do you want to remove remote files in dir: {remote_io.env_dir}?"
             )
         ):
             remote_io.delete_all()
Exemple #4
0
def jupyter_kernel_install_query(name: str, packages: Packages):
    """A function to install conda env as jupyter kernel if user agrees"""
    if any(pkg.name.startswith("jupyter") for pkg in packages):
        try:
            if _jupyter_kernel_exists(name=name):
                logger.debug(
                    f"{name} is already installed as a jupyter kernel")
            else:
                if prompt_yes_no(
                        prompt_msg=f"Would you like to register {name} as a "
                        "jupyter kernel available from another environment"):
                    _install_conda_jupyter_kernel(name=name)
        except JupyterKernelInstallError as err:
            logger.debug(f"Error while installing jupyter kernel: {str(err)}")
Exemple #5
0
def _create_env_with_new_id(env: Environment, remote_history: History,
                            yes: bool):
    if env.history and remote_history and env.history.id != remote_history.id:
        if yes or prompt_yes_no(
                prompt_msg=
            (f"The remote cet environment ({env.local_io.get_remote_dir()}) doesn't match the local environment ({env.name})\n"
             "Would you like to replace your local environment"),
                default=False,
        ):
            return True
        raise CondaEnvTrackerCreationError(
            f"The remote environment ({env.local_io.get_remote_dir()}) appears to be new environment and would replace the current local environment ({env.name})\n"
            "User elected not to update")
    return False
Exemple #6
0
def _local_needs_update(local_history: History,
                        remote_history: History,
                        yes: bool = True) -> bool:
    """Either the local does not yet exist or local is a subset of remote."""
    if not local_history and remote_history:
        return True
    if _no_new_actions_in_local(local_history=local_history,
                                remote_history=remote_history):
        return True
    if _actions_in_different_order(local_history=local_history,
                                   remote_history=remote_history):
        if not yes and not prompt_yes_no(
                prompt_msg=
                "Remote environment has same packages but in different order, "
                "Should we overwrite local with remote environment"):
            raise CondaEnvTrackerPullError(
                "Actions in a different order; user elected not to update")
        return True
    return False
Exemple #7
0
def pull(env: Environment, yes: bool = False) -> Environment:
    """Pull history from remote to local"""
    try:
        remote_dir = env.local_io.get_remote_dir()
    except CondaEnvTrackerRemoteError as remote_err:
        raise CondaEnvTrackerPullError(str(remote_err))
    remote_io = EnvIO(env_directory=remote_dir)
    remote_history = remote_io.get_history()

    local_history = env.history

    if _create_env_with_new_id(env=env, remote_history=remote_history,
                               yes=yes):
        return replace_local_with_remote(
            env=env,
            remote_dir=remote_dir,
            remote_io=remote_io,
            remote_history=remote_history,
        )
    if _nothing_to_pull(local_history=local_history,
                        remote_history=remote_history):
        logger.info("Nothing to pull.")
        return env
    if _local_needs_update(local_history=local_history,
                           remote_history=remote_history,
                           yes=yes):
        return replace_local_with_remote(
            env=env,
            remote_dir=remote_dir,
            remote_io=remote_io,
            remote_history=remote_history,
        )

    if not yes and not prompt_yes_no(prompt_msg=(
            "Remote and local have different packages, do you want to overwrite "
            "with remote and append local")):
        logger.info("Exiting without updating local environment.")
        raise CondaEnvTrackerPullError(
            "Conflicting Packages in remote and local; user elected not to update"
        )

    return merge_conflicting_changes(env=env)
Exemple #8
0
def pull(env: Environment, yes: bool = False) -> Environment:
    """Pull history from remote to local"""
    remote_dir = env.local_io.get_remote_dir()
    remote_io = EnvIO(env_directory=remote_dir)
    remote_history = remote_io.get_history()

    local_history = env.history

    _check_for_errors(local_history=local_history, remote_history=remote_history)

    if _nothing_to_pull(local_history=local_history, remote_history=remote_history):
        logger.info("Nothing to pull.")
        return env
    if _local_needs_update(local_history=local_history, remote_history=remote_history):
        update(
            env=env,
            remote_dir=remote_dir,
            remote_io=remote_io,
            remote_history=remote_history,
        )
        return env
    if _actions_in_different_order(
        local_history=local_history, remote_history=remote_history
    ):
        if not yes and not prompt_yes_no(
            prompt_msg="Remote environment has same packages but in different order, "
            "Should we overwrite local with remote environment"
        ):
            logger.info("Exiting without updating local environment.")
            return env
        update(
            env=env,
            remote_dir=remote_dir,
            remote_io=remote_io,
            remote_history=remote_history,
        )
        return env
    if not yes and not prompt_yes_no(
        prompt_msg=(
            "Remote and local have different packages, do you want to overwrite "
            "with remote and append local"
        )
    ):
        logger.info("Exiting without updating local environment.")
        return env
    update_conda_environment(env_dir=remote_dir)
    if _r_env_needs_updating(
        local_history=local_history, remote_history=remote_history
    ):
        update_r_environment(name=env.name, env_dir=remote_dir)
    EnvIO.overwrite_local(local_io=env.local_io, remote_io=remote_io)
    new_env = Environment(name=env.name, history=remote_history)
    new_env.validate()
    extra_logs = []
    for log in local_history.logs:
        if log not in set(remote_history.logs):
            extra_logs.append(log)
    for log in extra_logs:
        new_env = _update_from_extra_log(env=new_env, history=local_history, log=log)
    new_env = _update_r_packages(
        env=new_env, local_history=local_history, remote_history=remote_history
    )

    new_env.validate()
    new_env.export()

    env.history = new_env.history
    logger.info("Successfully updated the environment.")
    return new_env
def test_prompt_yes_no_default(mocker):
    patch = mocker.patch("conda_env_tracker.utils.input", return_value="y")
    prompt_yes_no(prompt_msg="", default=True)
    patch.assert_called_with(" ([y]/n)? ")
    prompt_yes_no(prompt_msg="", default=False)
    patch.assert_called_with(" (y/[n])? ")
Exemple #10
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