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)
示例#2
0
def test_pull_no_new_action_in_local(setup_tests):
    overwrite_mock = setup_tests["overwrite_mock"]
    remote_history = setup_tests["remote_history"]

    local_packages = (Package.from_spec("pandas"), )
    local_logs = ["conda create --name pull_testing_environment pandas"]
    local_actions = [
        "conda create --name pull_testing_environment pandas=0.23=py36"
    ]

    local_history = History(
        name=ENV_NAME,
        packages=HistoryPackages.create(local_packages),
        channels=Channels(),
        logs=Logs([log for log in local_logs]),
        actions=Actions(local_actions),
        debug=Debug(),
    )
    env = Environment(name=ENV_NAME, history=local_history)

    pull(env=env)

    assert env.history.packages == remote_history.packages
    assert env.history.logs == remote_history.logs
    assert env.history.actions == remote_history.actions
    overwrite_mock.called_once()
示例#3
0
 def write_history_file(self, history: History) -> None:
     """write/update history yaml file"""
     self._setup_env_dir()
     history_file = self.env_dir / "history.yaml"
     contents = yaml.dump(history.export(), default_flow_style=False)
     formatted = self._format_yaml(contents)
     history_file.write_text(formatted)
def test_get_packages_with_version_spec(mocker):
    mocker.patch(
        "conda_env_tracker.env.get_dependencies",
        return_value={
            "conda": {
                "pandas": Package("pandas", "pandas", "0.23", "py_36"),
                "numpy": Package("numpy", "numpy", "0.13", "py_36"),
            },
            "pip": {
                "pytest": Package("pytest", "pytest", "4.0")
            },
        },
    )
    local_packages = HistoryPackages.create(
        (Package.from_spec("pandas=0.23"), ))
    local_packages.update_packages(
        packages=(Package.from_spec("pytest==4.0"), ), source="pip")
    local_history = History(
        name=ENV_NAME,
        packages=local_packages,
        channels=Channels("defaults"),
        logs=Logs([]),
        actions=Actions(),
        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
示例#5
0
def test_parse_with_package():
    """Test to parse yaml file without any package"""
    history = History.parse({
        "channels": ["conda-forge", "main"],
        "packages": {
            "conda": {
                "pytest": "*"
            }
        },
        "logs": ["conda create --name test pytest"],
        "actions": [
            "conda create --name test pytest=0.1=py36_0 "
            "--channel conda-forge "
            "--channel main"
        ],
        "debug": [{
            "platform": "linux",
            "conda_version": "4.5.11"
        }],
    })
    assert ["conda-forge", "main"] == history.channels
    assert {
        "conda": {
            "pytest": Package.from_spec("pytest")
        }
    } == history.packages
    assert ["conda create --name test pytest"] == history.logs
    assert [
        "conda create --name test pytest=0.1=py36_0 "
        "--channel conda-forge "
        "--channel main"
    ] == history.actions
    assert [{"platform": "linux", "conda_version": "4.5.11"}] == history.debug
示例#6
0
def test_parse_with_package_with_version():
    """Test to parse yaml file without any package"""
    history = History.parse({
        "name":
        "environment-name",
        "channels": ["conda-forge", "main"],
        "packages": {
            "conda": {
                "pytest": "3.7=py36_0"
            }
        },
        "logs": ["conda create --name test pytest=3.7=py36_0"],
        "actions": ["conda create --name test pytest=3.7=py36_0"],
        "debug": [{
            "platform": "osx",
            "conda_version": "4.5.12"
        }],
    })
    assert history.name == "environment-name"
    assert history.channels == ["conda-forge", "main"]
    assert history.packages == {
        "conda": {
            "pytest": Package.from_spec("pytest=3.7=py36_0")
        }
    }
    assert history.logs == ["conda create --name test pytest=3.7=py36_0"]
    assert history.actions == ["conda create --name test pytest=3.7=py36_0"]
    assert history.debug == [{"platform": "osx", "conda_version": "4.5.12"}]
示例#7
0
def diff(name: str) -> ListLike:
    """Get the difference between history yaml and local conda environment"""
    env = Environment.read(name=name)
    env_reader = EnvIO(env_directory=USER_ENVS_DIR / name)
    version_diff_pkges, new_pkges, missing_pkges = History.history_diff(
        env_name=name, env=env, env_reader=env_reader)
    return missing_pkges + version_diff_pkges + new_pkges
示例#8
0
def test_pull_new_action_in_both(setup_tests, local_packages, local_logs,
                                 local_actions):
    overwrite_mock = setup_tests["overwrite_mock"]
    remote_history = setup_tests["remote_history"]
    packages_mock = setup_tests["get_dependencies"]

    packages = HistoryPackages.create(local_packages["conda"])
    if local_packages.get("pip"):
        packages.update_packages(local_packages["pip"], source="pip")

    local_history = History(
        name=ENV_NAME,
        channels=CHANNELS,
        packages=packages,
        logs=Logs([log for log in local_logs]),
        actions=Actions(local_actions),
        debug=Debug(),
    )
    env = Environment(name=ENV_NAME, history=local_history)

    if local_packages.get("pip") is not None:
        packages_mock.configure_mock(
            return_value={
                "conda": {
                    "pandas": Package("pandas", "pandas", "0.23", "py36"),
                    "pytest": Package("pytest", "pytest", "0.1", "py36_3"),
                },
                "pip": {
                    "pylint": Package("pylint", "pylint", "1.11")
                },
            })
    else:
        packages_mock.configure_mock(
            return_value={
                "conda": {
                    "pandas": Package("pandas", "pandas", "0.23", "py36"),
                    "pytest": Package("pytest", "pytest", "0.1", "py36_3"),
                    "pylint": Package("pylint", "pylint", "1.11", "py36"),
                },
                "pip": {},
            })

    pull(env=env)

    expected_packages = remote_history.packages
    if local_packages.get("pip"):
        expected_packages["pip"]["pylint"] = local_history.packages["pip"][
            "pylint"]
    elif "pylint" in local_history.packages["conda"]:
        expected_packages["conda"]["pylint"] = local_history.packages["conda"][
            "pylint"]
    expected_logs = remote_history.logs
    expected_actions = remote_history.actions

    assert env.history.packages == expected_packages
    assert env.history.logs == expected_logs
    assert env.history.actions == expected_actions
    assert env.history.logs[-1] == local_history.logs[-1]
    assert env.history.actions[-1] == local_history.actions[-1]
    overwrite_mock.called_once()
示例#9
0
 def get_history(self) -> Optional[History]:
     """return history from history.yaml"""
     log_file = self.env_dir / "history.yaml"
     if log_file.is_file():
         log_content = log_file.read_text()
         return History.parse(yaml.load(log_content, Loader=yaml.FullLoader))
     return None
示例#10
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
示例#11
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
示例#12
0
def test_export(mocker):
    name = "test-export"

    io_mock = mocker.patch("conda_env_tracker.env.EnvIO")
    mocker.patch(
        "conda_env_tracker.env.get_dependencies",
        mocker.Mock(
            return_value={
                "conda": {
                    "python":
                    Package("python", "python=3.7.2=buildstr", "3.7.2",
                            "buildstr")
                },
                "pip": {},
            }),
    )
    mocker.patch("conda_env_tracker.history.get_pip_version",
                 mocker.Mock(return_value="18.1"))

    history = History.parse({
        "name":
        name,
        "channels": ["conda-forge", "main"],
        "packages": {
            "conda": {
                "python": "3.7.2=buildstr"
            }
        },
        "logs": ["conda create --name test python=3.7"],
        "actions": ["conda create --name test python=3.7.2=buildstr"],
        "debug": [{
            "platform": "osx",
            "conda_version": "4.6.1",
            "pip_version": "18.1"
        }],
    })

    env = Environment(name=name, history=history)

    env.export()

    expected = """name: test-export
channels:
- conda-forge
- main
- nodefaults
dependencies:
- python=3.7.2=buildstr
"""

    assert io_mock.mock_calls == [
        mocker.call(env_directory=Path(USER_ENVS_DIR / name)),
        mocker.call().write_history_file(history=history),
        mocker.call().export_packages(
            contents=expected.replace("=buildstr", "")),
        mocker.call().delete_install_r(),
    ]
示例#13
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
示例#14
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
示例#15
0
def setup_r_tests(mocker):
    """Set up for pull function with R packages"""
    remote_packages = Packages.from_specs("r-base")
    remote_logs = ["conda create --name pull_testing_environment r-base"]
    remote_actions = [
        "conda create --name pull_testing_environment r-base=3.5.1=h351"
    ]
    remote_history = History(
        name=ENV_NAME,
        channels=CHANNELS,
        packages=HistoryPackages.create(remote_packages),
        logs=Logs([log for log in remote_logs]),
        actions=Actions(remote_actions),
        debug=Debug(),
    )

    mocker.patch("conda_env_tracker.conda.conda_install")
    mocker.patch("conda_env_tracker.pip.pip_install")
    mocker.patch("conda_env_tracker.history.get_pip_version")

    run_mock = mocker.patch("conda_env_tracker.gateways.r.run_command")
    run_mock.configure_mock(**{"return_value.failed": False})

    mocker.patch(
        "conda_env_tracker.env.get_dependencies",
        return_value={"conda": {
            "r-base": "3.5.1"
        }},
    )
    get_r_dependencies = mocker.patch(
        "conda_env_tracker.env.get_r_dependencies")
    overwrite_mock = mocker.patch(
        "conda_env_tracker.pull.EnvIO.overwrite_local")
    mocker.patch("conda_env_tracker.pull.EnvIO.get_remote_dir",
                 return_value="~/path/to/remote")
    mocker.patch("conda_env_tracker.pull.EnvIO.get_history",
                 return_value=remote_history)
    mocker.patch("conda_env_tracker.pull.prompt_yes_no", return_value=True)
    mocker.patch("conda_env_tracker.pull.update_conda_environment")
    mocker.patch("conda_env_tracker.pull.update_r_environment")
    mocker.patch("conda_env_tracker.pull.Environment.export")
    mocker.patch("conda_env_tracker.pull.Environment.validate")

    yield {
        "get_r_dependencies": get_r_dependencies,
        "overwrite_mock": overwrite_mock,
        "remote_history": remote_history,
    }

    env_dir = USER_ENVS_DIR / ENV_NAME
    if env_dir.exists():
        shutil.rmtree(env_dir)
示例#16
0
def setup_tests(mocker):
    """Set up for pull function"""
    remote_packages = (Package.from_spec("pandas"),
                       Package.from_spec("pytest"))
    remote_logs = [
        "conda create --name pull_testing_environment pandas",
        "conda install --name pull_testing_environment pytest",
    ]
    remote_actions = [
        "conda create --name pull_testing_environment pandas=0.23=py36",
        "conda install --name pull_testing_environment pytest=0.1=py36_3",
    ]
    remote_history = History(
        name=ENV_NAME,
        channels=CHANNELS,
        packages=HistoryPackages.create(remote_packages),
        logs=Logs([log for log in remote_logs]),
        actions=Actions(remote_actions),
        debug=Debug(),
    )

    mocker.patch("conda_env_tracker.conda.conda_install")
    mocker.patch("conda_env_tracker.conda.conda_update_all")
    mocker.patch("conda_env_tracker.conda.conda_remove")
    mocker.patch("conda_env_tracker.pip.pip_install")
    mocker.patch("conda_env_tracker.pip.pip_remove")
    mocker.patch("conda_env_tracker.history.get_pip_version")
    get_dependencies = mocker.patch("conda_env_tracker.env.get_dependencies")

    overwrite_mock = mocker.patch(
        "conda_env_tracker.pull.EnvIO.overwrite_local")
    mocker.patch("conda_env_tracker.pull.EnvIO.get_remote_dir",
                 return_value="~/path/to/remote")
    mocker.patch("conda_env_tracker.pull.EnvIO.get_history",
                 return_value=remote_history)
    mocker.patch("conda_env_tracker.pull.prompt_yes_no", return_value=True)
    mocker.patch("conda_env_tracker.pull.update_conda_environment")
    mocker.patch("conda_env_tracker.pull.update_r_environment")
    mocker.patch("conda_env_tracker.pull.Environment.export")
    mocker.patch("conda_env_tracker.pull.Environment.validate")
    mocker.patch(
        "conda_env_tracker.pull.Environment.validate_installed_packages")

    yield {
        "get_dependencies": get_dependencies,
        "overwrite_mock": overwrite_mock,
        "remote_history": remote_history,
    }

    env_dir = USER_ENVS_DIR / ENV_NAME
    if env_dir.exists():
        shutil.rmtree(env_dir)
示例#17
0
def test_parse_without_package():
    """Test to parse yaml file without any package"""
    history = History.parse({
        "channels": None,
        "packages": None,
        "logs": None,
        "actions": None,
        "debug": None,
    })
    assert [] == history.channels
    assert {} == history.packages
    assert [] == history.logs
    assert [] == history.actions
    assert [] == history.debug
示例#18
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)
示例#19
0
def test_write_history_file(env_io):
    """Test to create history yaml file and test get history"""
    env_io.write_history_file(
        History(
            name="",
            channels=Channels([]),
            packages=HistoryPackages({}),
            logs=Logs([]),
            actions=Actions([]),
            debug=[],
        ))
    assert [] == env_io.get_history().channels
    assert {} == env_io.get_history().packages
    assert [] == env_io.get_history().logs
    assert [] == env_io.get_history().debug
示例#20
0
def test_pull_remote_local_different_create_commands(setup_tests,
                                                     local_packages,
                                                     local_logs,
                                                     local_actions):
    # pylint: disable=unused-argument
    local_history = History(
        name=ENV_NAME,
        channels=CHANNELS,
        packages=HistoryPackages.create(local_packages),
        logs=Logs([log for log in local_logs]),
        actions=Actions(local_actions),
        debug=Debug(),
    )
    env = Environment(name=ENV_NAME, history=local_history)

    with pytest.raises(CondaEnvTrackerCreationError):
        pull(env=env)
示例#21
0
def test_get_packages_r(mocker):
    mocker.patch(
        "conda_env_tracker.env.get_dependencies",
        return_value={
            "conda": {
                "r-base":
                Package("r-base", "r-base", "3.5.1", "h539"),
                "r-devtools":
                Package("r-devtools", "r-devtools", "0.1.0", "r351_0"),
            }
        },
    )
    mocker.patch(
        "conda_env_tracker.env.get_r_dependencies",
        return_value={
            "trelliscopejs": Package("trelliscopejs", "trelliscopejs"
                                     "0.1.0")
        },
    )
    local_packages = HistoryPackages.create(
        Packages(
            (Package.from_spec("r-base"), Package.from_spec("r-devtools"))))
    local_packages.update_packages(
        packages=(Package.from_spec("trelliscopejs"), ), source="r")
    local_history = History(
        name=ENV_NAME,
        packages=local_packages,
        channels=Channels("defaults"),
        logs=Logs([]),
        actions=Actions(),
        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
示例#22
0
def test_export_empty():
    """Test package export"""
    expected = {
        "name": "",
        "channels": [],
        "packages": {},
        "logs": [],
        "actions": [],
        "debug": [],
    }
    actual = History(
        name="",
        channels=Channels(channels=[]),
        packages=HistoryPackages(),
        logs=Logs(),
        actions=Actions([]),
        debug=[],
    ).export()
    assert expected == actual
示例#23
0
def test_pull_actions_in_different_order(setup_tests):
    overwrite_mock = setup_tests["overwrite_mock"]
    remote_history = setup_tests["remote_history"]

    new_log = "conda install --name pull_testing_environment pylint"
    new_action = "conda install --name pull_testing_environment pylint=1.11=py36"

    remote_history.packages["pylint"] = "*"
    remote_history.logs.append(new_log)
    remote_history.actions.append(new_action)

    local_packages = (
        Package.from_spec("pandas"),
        Package.from_spec("pylint"),
        Package.from_spec("pytest"),
    )
    local_logs = [
        "conda create --name pull_testing_environment pandas",
        new_log,
        "conda install --name pull_testing_environment pytest",
    ]
    local_actions = [
        "conda create --name pull_testing_environment pandas=0.23=py36",
        new_action,
        "conda install --name pull_testing_environment pytest=0.1=py36_3",
    ]
    local_history = History(
        name=ENV_NAME,
        channels=CHANNELS,
        packages=HistoryPackages.create(local_packages),
        logs=Logs([log for log in local_logs]),
        actions=Actions(local_actions),
        debug=Debug(),
    )
    env = Environment(name=ENV_NAME, history=local_history)

    pull(env=env)

    assert env.history.packages == remote_history.packages
    assert env.history.logs == remote_history.logs
    assert env.history.actions == remote_history.actions
    overwrite_mock.called_once()
示例#24
0
def test_pull_no_new_action_in_remote(setup_tests, local_packages, local_logs,
                                      local_actions):
    overwrite_mock = setup_tests["overwrite_mock"]

    local_history = History(
        name=ENV_NAME,
        packages=HistoryPackages.create(local_packages),
        channels=Channels(),
        logs=Logs([log for log in local_logs]),
        actions=Actions(local_actions),
        debug=Debug(),
    )
    env = Environment(name=ENV_NAME, history=local_history)

    pull(env=env)

    assert env.history.packages == local_history.packages
    assert env.history.logs == local_history.logs
    assert env.history.actions == local_history.actions
    overwrite_mock.assert_not_called()
示例#25
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
示例#26
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)
示例#27
0
def test_export_success():
    """Test package export"""
    expected = {
        "name":
        "environment-name",
        "channels": ["conda-forge", "main"],
        "packages": {
            "conda": {
                "pytest": "*"
            }
        },
        "logs": ["conda create --name test pytest"],
        "actions": [
            "conda create --name test pytest=0.1=py36_0 "
            "--channel conda-forge "
            "--channel main"
        ],
        "debug": [{
            "platform": "osx",
            "conda_version": "4.5.10"
        }],
    }
    actual = History(
        name="environment-name",
        channels=Channels(["conda-forge", "main"]),
        packages=HistoryPackages(conda=dict(
            pytest=Package.from_spec("pytest"))),
        logs=Logs(["conda create --name test pytest"]),
        actions=Actions([
            "conda create --name test pytest=0.1=py36_0 "
            "--channel conda-forge "
            "--channel main"
        ]),
        debug=[{
            "platform": "osx",
            "conda_version": "4.5.10"
        }],
    ).export()
    assert expected == actual
示例#28
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
示例#29
0
def test_get_packages_conda(mocker):
    mocker.patch(
        "conda_env_tracker.env.get_dependencies",
        return_value={
            "conda": {
                "pandas": Package("pandas", "pandas", "0.23", "py_36"),
                "numpy": Package("numpy", "numpy", "0.13", "py_36"),
            }
        },
    )
    packages = (Package.from_spec("pandas"), )
    local_history = History(
        name=ENV_NAME,
        packages=HistoryPackages.create(packages),
        channels=Channels("defaults"),
        logs=Logs([]),
        actions=Actions(),
        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
示例#30
0
def test_ignore_empty_pip_packages():
    """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.
    """
    expected = {
        "name": "environment-name",
        "channels": ["main"],
        "packages": {
            "conda": {
                "pytest": "*"
            }
        },
        "logs": ["conda create --name test pytest"],
        "actions":
        ["conda create --name test pytest=0.1=py36_0 "
         "--channel main"],
        "debug": [{
            "platform": "osx",
            "conda_version": "4.5.10"
        }],
    }
    actual = History(
        name="environment-name",
        channels=Channels(["main"]),
        packages=HistoryPackages(
            conda=dict(pytest=Package.from_spec("pytest")), pip={}),
        logs=Logs(["conda create --name test pytest"]),
        actions=Actions(
            ["conda create --name test pytest=0.1=py36_0 "
             "--channel main"]),
        debug=[{
            "platform": "osx",
            "conda_version": "4.5.10"
        }],
    ).export()
    assert expected == actual