def setup(mocker, request):
    """Set up for diff function"""
    local_packages = request.param["local_packages"]
    local_logs = request.param["local_logs"]
    local_actions = request.param["local_actions"]
    env_name = request.param["env_name"]

    remote_packages = request.param["remote_packages"]
    remote_logs = request.param["remote_logs"]
    remote_actions = request.param["remote_actions"]

    dependencies = {
        "conda": {
            "pandas": Package("pandas", "pandas", version="0.23.0"),
            "pytest": Package("pytest", "pytest", version="4.0.0"),
        }
    }
    mocker.patch(
        "conda_env_tracker.env.get_dependencies", mocker.Mock(return_value=dependencies)
    )
    history = History.create(
        name=env_name,
        packages=PackageRevision.create(local_packages, dependencies=dependencies),
        channels=Channels(["conda-forge"]),
        logs=Logs([log for log in local_logs]),
        actions=local_actions,
        diff=Diff(),
        debug=Debug(),
    )
    env = Environment(name=env_name, history=history)
    mocker.patch("conda_env_tracker.main.Environment.read", return_value=env)

    mocker.patch(
        "conda_env_tracker.gateways.io.EnvIO.get_remote_dir",
        return_value="~/path/to/remote",
    )
    mocker.patch("pathlib.Path.is_dir", return_value=True)
    history = History.create(
        name=env_name,
        channels=Channels(["conda-forge"]),
        packages=PackageRevision.create(remote_packages, dependencies=dependencies),
        logs=Logs([log for log in remote_logs]),
        actions=remote_actions,
        diff=Diff(),
        debug=Debug(),
    )
    mocker.patch(
        "conda_env_tracker.gateways.io.EnvIO.get_history", return_value=history
    )
    mocker.patch("pathlib.Path.write_text")

    yield env, request.param["push_should_fail"]

    if (USER_ENVS_DIR / env_name).exists():
        shutil.rmtree(USER_ENVS_DIR / env_name)
Beispiel #2
0
def test_get_packages_with_version_spec(mocker):
    dependencies = {
        "conda": {
            "pandas": Package("pandas", "pandas", "0.23", "py_36"),
            "numpy": Package("numpy", "numpy", "0.13", "py_36"),
        },
        "pip": {
            "pytest": Package("pytest", "pytest", "4.0")
        },
    }
    mocker.patch("conda_env_tracker.env.get_dependencies",
                 return_value=dependencies)
    mocker.patch("conda_env_tracker.env.get_dependencies",
                 return_value=dependencies)
    local_packages = PackageRevision.create(
        (Package.from_spec("pandas=0.23"), ), dependencies=dependencies)
    local_packages.update_packages(
        packages=(Package.from_spec("pytest==4.0"), ), source="pip")
    local_history = History.create(
        name=ENV_NAME,
        packages=local_packages,
        channels=Channels("defaults"),
        logs=Logs([]),
        actions=Actions(),
        diff=Diff(),
        debug=Debug(),
    )
    env = Environment(name=ENV_NAME, history=local_history)

    expected = {
        "conda": [Package("pandas", "pandas=0.23", "0.23", "py_36")],
        "pip": [Package("pytest", "pytest==4.0", "4.0")],
    }
    actual = get_packages(env)
    assert actual == expected
Beispiel #3
0
def test_export_success(mocker):
    """Test package export"""
    mocker.patch(
        "conda_env_tracker.history.history.uuid4").return_value = "unique_uuid"
    expected = {
        "name":
        "environment-name",
        "id":
        "unique_uuid",
        "history-file-version":
        "1.0",
        "channels": ["conda-forge", "main"],
        "packages": {
            "conda": {
                "pytest": "*"
            }
        },
        "revisions": [{
            "log":
            "conda create --name test pytest",
            "action":
            "conda create --name test pytest=4.0=py36_0 "
            "--channel conda-forge "
            "--channel main",
            "debug": {
                "platform": "osx",
                "conda_version": "4.5.10"
            },
            "packages": {
                "conda": {
                    "pytest": "*"
                }
            },
            "diff": {
                "conda": {
                    "upsert": ["pytest=4.0"]
                }
            },
        }],
    }
    actual = History.create(
        name="environment-name",
        channels=Channels(["conda-forge", "main"]),
        packages=PackageRevision(conda=dict(
            pytest=Package.from_spec("pytest"))),
        logs=Logs(["conda create --name test pytest"]),
        actions=Actions([
            "conda create --name test pytest=4.0=py36_0 "
            "--channel conda-forge "
            "--channel main"
        ]),
        diff=Diff(conda=dict(upsert=dict(
            pytest=Package("pytest", version="4.0")))),
        debug=[{
            "platform": "osx",
            "conda_version": "4.5.10"
        }],
    ).export()
    assert expected == actual
Beispiel #4
0
def test_ignore_empty_pip_packages(mocker):
    """When a user installs a pip package and then removes it, the pip packages is an empty dictionry which
    does not need to show up in the history file.
    """
    mocker.patch(
        "conda_env_tracker.history.history.uuid4").return_value = "unique_uuid"
    expected = {
        "name":
        "environment-name",
        "id":
        "unique_uuid",
        "history-file-version":
        "1.0",
        "channels": ["main"],
        "packages": {
            "conda": {
                "pytest": "*"
            }
        },
        "revisions": [{
            "log": "conda create --name test pytest",
            "action": "conda create --name test pytest=4.0=py36_0 "
            "--channel main",
            "debug": {
                "platform": "osx",
                "conda_version": "4.5.10"
            },
            "packages": {
                "conda": {
                    "pytest": "*"
                }
            },
            "diff": {
                "conda": {
                    "upsert": ["pytest=4.0"]
                }
            },
        }],
    }
    actual = History.create(
        name="environment-name",
        channels=Channels(["main"]),
        packages=PackageRevision(
            conda=dict(pytest=Package.from_spec("pytest")), pip={}),
        logs=Logs(["conda create --name test pytest"]),
        actions=Actions(
            ["conda create --name test pytest=4.0=py36_0 "
             "--channel main"]),
        diff=Diff(
            dict(conda=dict(upsert=dict(
                pytest=Package("pytest", version="4.0"))))),
        debug=[{
            "platform": "osx",
            "conda_version": "4.5.10"
        }],
    ).export()
    assert expected == actual
Beispiel #5
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"
            )

        dependencies = get_dependencies(name=name)
        if "r-base" in dependencies["conda"]:
            dependencies["r"] = get_r_dependencies(name=name)

        user_packages = {"conda": Packages(), "pip": Packages()}
        for package in packages:
            if package.name in dependencies.get("conda", Packages()):
                user_packages["conda"].append(package)
            elif package.name in dependencies.get("pip", Packages()):
                user_packages["pip"].append(package)
            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=dependencies["conda"]
        )

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

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

        return env
Beispiel #6
0
def test_write_history_file(env_io):
    """Test to create history yaml file and test get history"""
    env_io.write_history_file(
        History.create(
            name="test-env",
            channels=Channels(["main"]),
            packages=PackageRevision(
                {"conda": {
                    "python": Package.from_spec("python")
                }}),
            logs=Logs(["conda create -n test-env python"]),
            actions=Actions([
                "conda create -n test-env python=3.7.3=buildstring --override-channels --channel main"
            ]),
            diff=Diff({
                "conda": {
                    "upsert": {
                        "python": Package("python", version="3.7.3")
                    }
                }
            }),
            debug=["blah"],
        ))
    assert ["main"] == env_io.get_history().channels
    assert {
        "conda": {
            "python": Package.from_spec("python")
        }
    } == env_io.get_history().packages
    assert (Revisions(
        **{
            "logs": ["conda create -n test-env python"],
            "actions": [
                "conda create -n test-env python=3.7.3=buildstring --override-channels --channel main"
            ],
            "packages": [{
                "conda": {
                    "python": Package.from_spec("python")
                }
            }],
            "diffs": [{
                "conda": {
                    "upsert": {
                        "python": Package("python", "python", version="3.7.3")
                    }
                }
            }],
            "debug": ["blah"],
        }) == env_io.get_history().revisions)
Beispiel #7
0
def test_get_packages_r(mocker):
    dependencies = {
        "conda": {
            "r-base": Package("r-base", "r-base", "3.5.1", "h539"),
            "r-devtools": Package("r-devtools", "r-devtools", "0.1.0",
                                  "r351_0"),
        }
    }
    r_dependencies = {
        "trelliscopejs": Package("trelliscopejs", "trelliscopejs"
                                 "0.1.0")
    }
    mocker.patch("conda_env_tracker.env.get_dependencies",
                 return_value=dependencies)
    mocker.patch("conda_env_tracker.env.get_r_dependencies",
                 return_value=r_dependencies)
    local_packages = PackageRevision.create(
        Packages(
            (Package.from_spec("r-base"), Package.from_spec("r-devtools"))),
        dependencies=dependencies,
    )
    local_packages.update_packages(
        packages=(Package.from_spec("trelliscopejs"), ), source="r")
    local_history = History.create(
        name=ENV_NAME,
        packages=local_packages,
        channels=Channels("defaults"),
        logs=Logs([]),
        actions=Actions(),
        diff=Diff(),
        debug=Debug(),
    )
    env = Environment(name=ENV_NAME, history=local_history)

    expected = {
        "conda": [
            Package("r-base", "r-base", "3.5.1", "h539"),
            Package("r-devtools", "r-devtools", "0.1.0", "r351_0"),
        ],
        "r": [Package("trelliscopejs", "trelliscopejs", "0.1.0")],
    }
    actual = get_packages(env)
    assert actual == expected
Beispiel #8
0
def test_export_empty(mocker):
    """Test package export"""
    mocker.patch(
        "conda_env_tracker.history.history.uuid4").return_value = "unique_uuid"
    expected = {
        "name": "",
        "id": "unique_uuid",
        "history-file-version": "1.0",
        "channels": [],
        "packages": {},
        "revisions": [],
    }
    actual = History.create(
        name="",
        channels=Channels(channels=[]),
        packages=PackageRevision(),
        logs=Logs(),
        actions=Actions([]),
        diff=Diff(),
        debug=[],
    ).export()
    assert expected == actual
Beispiel #9
0
def expected_diff(mocker, request):
    """Set up for diff function"""

    packages = request.param["packages"]
    conda_dependencies = request.param["conda_dependencies"]
    local = request.param["local"]
    name = "test-diff"
    mocker.patch("conda_env_tracker.gateways.io.Path.mkdir")
    mocker.patch("conda_env_tracker.gateways.io.Path.write_text")
    dependencies = {"conda": conda_dependencies, "pip": {}}
    mocker.patch("conda_env_tracker.env.get_dependencies",
                 mocker.Mock(return_value=dependencies))
    history = History.create(
        name=name,
        packages=PackageRevision.create(packages=packages,
                                        dependencies=dependencies),
        channels=None,
        logs=None,
        actions=None,
        debug=None,
        diff=None,
    )
    env = Environment(name=name, history=history)
    mocker.patch("conda_env_tracker.main.Environment.read", return_value=env)
    mocker.patch(
        "conda_env_tracker.gateways.io.EnvIO.get_environment",
        return_value={
            "name": "test-diff",
            "channels": ["conda-forge"],
            "dependencies": dependencies,
        },
    )
    mocker.patch(
        "conda_env_tracker.history.history.get_dependencies",
        return_value={"conda": local},
    )
    yield request.param["expected"]
    if (USER_ENVS_DIR / name).exists():
        shutil.rmtree(USER_ENVS_DIR / name)
Beispiel #10
0
def expected_update(mocker):
    """Set up for update function"""
    packages = Packages.from_specs("pandas")
    channel = "conda-forge"
    create_cmd = "conda install pandas"
    name = "test-update"
    mocker.patch("conda_env_tracker.gateways.io.Path.mkdir")
    mocker.patch("conda_env_tracker.gateways.io.Path.write_text")
    mocker.patch("conda_env_tracker.gateways.io.Path.iterdir")
    mocker.patch("conda_env_tracker.history.debug.get_pip_version",
                 return_value=None)
    dependencies = {
        "conda": {
            "pandas": Package("pandas", "pandas", "0.23", "py36"),
            "pytest": Package("pytest", "pytest", "0.1", "py36"),
        },
        "pip": {},
    }
    mocker.patch("conda_env_tracker.env.get_dependencies",
                 return_value=dependencies)
    mocker.patch("conda_env_tracker.env.EnvIO.export_packages")
    history = History.create(
        name=name,
        channels=Channels([channel]),
        packages=PackageRevision.create(packages, dependencies=dependencies),
        logs=Logs(create_cmd),
        actions=Actions.create(name="test-update",
                               specs=["pandas"],
                               channels=Channels([channel])),
        diff=Diff.create(packages, dependencies=dependencies),
        debug=Debug(),
    )
    mocker.patch(
        "conda_env_tracker.main.Environment.read",
        return_value=Environment(name=name, history=history),
    )
    return history
Beispiel #11
0
def test_get_packages_conda(mocker):
    dependencies = {
        "conda": {
            "pandas": Package("pandas", "pandas", "0.23", "py_36"),
            "numpy": Package("numpy", "numpy", "0.13", "py_36"),
        }
    }
    mocker.patch("conda_env_tracker.env.get_dependencies",
                 return_value=dependencies)
    packages = (Package.from_spec("pandas"), )
    local_history = History.create(
        name=ENV_NAME,
        packages=PackageRevision.create(packages, dependencies=dependencies),
        channels=Channels("defaults"),
        logs=Logs([]),
        actions=Actions(),
        diff=Diff(),
        debug=Debug(),
    )
    env = Environment(name=ENV_NAME, history=local_history)

    expected = {"conda": [Package("pandas", "pandas", "0.23", "py_36")]}
    actual = get_packages(env)
    assert actual == expected
Beispiel #12
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