Example #1
0
def test_pip_version(mocker):
    dep_mock = mocker.patch("conda_env_tracker.gateways.pip.get_dependencies")
    dep_mock.configure_mock(
        return_value={"conda": {"pip": Package("pip", "pip", "18.1", "py37_0")}}
    )

    version = pip.get_pip_version(name="env_name")

    assert version == "18.1"
Example #2
0
 def update(self, name: str) -> None:
     """Update with the current debug information."""
     pip_version = get_pip_version(name=name)
     self.append({
         "platform": get_platform_name(),
         "conda_version": CONDA_VERSION,
         "pip_version": pip_version,
         "timestamp": str(datetime.datetime.now()),
     })
Example #3
0
def test_history_after_create(end_to_end_setup):
    """Test the history.yaml in detail."""
    name = end_to_end_setup["name"]
    env_dir = end_to_end_setup["env_dir"]
    channels = end_to_end_setup["channels"]
    channel_command = end_to_end_setup["channel_command"]

    history_file = env_dir / "history.yaml"
    actual_history_content = history_file.read_text()
    print(actual_history_content)

    actual = yaml.load(actual_history_content, Loader=yaml.FullLoader)

    action_expected_pattern = rf"(conda create --name {name})(\s)(python=3.6)(.*)(\s)(colorama=)(.*)({channel_command})"

    expected_packages = {"conda": {"colorama": "*", "python": "3.6"}}
    expected_logs = [
        f"conda create --name {name} python=3.6 colorama {channel_command}"
    ]
    expected_debug = [{
        "platform": get_platform_name(),
        "conda_version": CONDA_VERSION,
        "pip_version": get_pip_version(name=name),
        "timestamp": str(date.today()),
    }]

    assert actual["packages"] == expected_packages
    assert actual["logs"] == expected_logs
    assert actual["channels"] == channels
    assert re.match(action_expected_pattern, actual["actions"][0])
    assert len(actual["actions"]) == 1
    for key, val in expected_debug[0].items():
        if key == "timestamp":
            assert actual["debug"][0][key].startswith(val)
        else:
            assert actual["debug"][0][key] == val

    expected_start = [f"name: {name}", "channels:"]
    for channel in channels:
        expected_start.append(f"  - {channel}")
    expected_history_start = "\n".join(expected_start + [
        "packages:",
        "  conda:",
        "    python: '3.6'",
        "    colorama: '*'",
        "logs:",
        "  - conda create --name end_to_end_test python=3.6 colorama --override-channels --strict-channel-priority",
        "    --channel main",
        "actions:",
        f"  - conda create --name {name} python=3.6",
    ])
    end = actual_history_content.rfind("python=3.6") + len("python=3.6")
    actual_history_start = actual_history_content[:end]
    assert actual_history_start == expected_history_start
def test_history_r_install(r_setup):
    """Test the history.yaml in detail."""
    # pylint: disable=line-too-long
    name = r_setup["name"]
    env = r_setup["env"]
    env_dir = r_setup["env_dir"]
    channels = r_setup["channels"]

    history_file = env_dir / "history.yaml"
    actual_history_content = history_file.read_text()
    print(actual_history_content)

    actual = yaml.load(actual_history_content, Loader=yaml.FullLoader)

    expected_packages = {
        "conda": {"r-base": "*", "r-devtools": "*"},
        "r": {
            "jsonlite": 'library("devtools"); install_version("jsonlite",version="1.2")',
            "praise": 'install.packages("praise")',
        },
    }

    expected_log = (
        r'R --quiet --vanilla -e "library(\"devtools\"); '
        r"install_version(\"jsonlite\",version=\"1.2\"); "
        r"install.packages(\"praise\")"
    )

    expected_action = (
        r'R --quiet --vanilla -e "library(\"devtools\"); '
        r"install_version(\"jsonlite\",version=\"1.2\",date=\"2019-01-01\"); "
        r'library(\"devtools\"); install_mran(\"praise\",version=\"1.0.0\",date=\"2019-01-01\")"'
    )

    expected_debug = 2 * [
        {
            "platform": get_platform_name(),
            "conda_version": CONDA_VERSION,
            "pip_version": pip.get_pip_version(name=name),
            "timestamp": str(date.today()),
        }
    ]
    assert actual["name"] == name
    assert actual["channels"] == channels
    assert actual["packages"] == expected_packages
    assert actual["revisions"][-1]["log"] == expected_log
    assert len(actual["revisions"]) == 2
    assert actual["revisions"][-1]["action"] == expected_action
    for i in range(len(actual["revisions"])):
        for key, val in expected_debug[i].items():
            if key == "timestamp":
                assert actual["revisions"][i]["debug"][key].startswith(val)
            else:
                assert actual["revisions"][i]["debug"][key] == val

    dependencies = env.dependencies

    expected_history = [
        f"name: {name}",
        f"id: {env.history.id}",
        "history-file-version: '1.0'",
        "channels:",
    ]
    for channel in channels:
        expected_history.append(f"  - {channel}")
    expected_history_start = "\n".join(
        expected_history
        + [
            "packages:",
            "  conda:",
            "    r-base: '*'",
            "    r-devtools: '*'",
            "  r:",
            '    jsonlite: library("devtools"); install_version("jsonlite",version="1.2")',
            '    praise: install.packages("praise")',
            "revisions:",
            "  - packages:",
            "      conda:",
            "        r-base: '*'",
            "        r-devtools: '*'",
            "    diff:",
            "      conda:",
            "        upsert:",
            f"        - r-base={dependencies['conda']['r-base'].version}",
            f"        - r-devtools={dependencies['conda']['r-devtools'].version}",
            "    log: conda create --name r_end_to_end_test r-base r-devtools --override-channels",
            "      --strict-channel-priority --channel r",
            "      --channel defaults",
            "    action: conda create --name r_end_to_end_test r-base",
        ]
    )
    expected_second_revision = "\n".join(
        [
            "  - packages:",
            "      conda:",
            "        r-base: '*'",
            "        r-devtools: '*'",
            "      r:",
            '        jsonlite: library("devtools"); install_version("jsonlite",version="1.2")',
            '        praise: install.packages("praise")',
            "    diff:",
            "      r:",
            "        upsert:",
            f"        - jsonlite",
            f"        - praise",
            r'    log: R --quiet --vanilla -e "library(\"devtools\"); install_version(\"jsonlite\",version=\"1.2\");',
            r"      install.packages(\"praise\")",
            r'    action: R --quiet --vanilla -e "library(\"devtools\"); install_version(\"jsonlite\",version=\"1.2\");',
            r"      install.packages(\"praise\")",
        ]
    )
    index_first_action = actual_history_content.find(
        "action: conda create --name r_end_to_end_test r-base"
    ) + len("action: conda create --name r_end_to_end_test r-base")
    actual_history_start = actual_history_content[:index_first_action]
    assert actual_history_start == expected_history_start

    index_second_revision_start = actual_history_content.find(
        "  - packages:", index_first_action
    )
    index_second_debug = actual_history_content.find(
        "debug:", index_second_revision_start
    )
    actual_second_revision = actual_history_content[
        index_second_revision_start:index_second_debug
    ].rstrip()
    assert actual_second_revision == expected_second_revision
Example #5
0
def test_remove_package(end_to_end_setup):
    """Test the removal of a package."""
    name = end_to_end_setup["name"]
    env_dir = end_to_end_setup["env_dir"]
    channels = end_to_end_setup["channels"]
    channel_command = end_to_end_setup["channel_command"].replace(
        "--strict-channel-priority ", "")

    conda_remove(name=name, specs=["colorama"], yes=True)

    actual_env_content = (env_dir / "conda-env.yaml").read_text()
    assert "colorama" not in actual_env_content

    log_file = env_dir / "history.yaml"
    actual_history_content = log_file.read_text()
    print(actual_history_content)

    actual = yaml.load(actual_history_content, Loader=yaml.FullLoader)

    expected_packages = {"conda": {"python": "3.6", "pytest": "*"}}
    expected_log = f"conda remove --name {name} colorama"
    expected_debug = {
        "platform": get_platform_name(),
        "conda_version": CONDA_VERSION,
        "pip_version": get_pip_version(name=name),
        "timestamp": str(date.today()),
    }

    assert actual["packages"] == expected_packages
    assert actual["logs"][-1] == expected_log
    assert len(actual["logs"]) == 3
    assert actual["channels"] == channels
    assert (actual["actions"][-1] ==
            f"conda remove --name {name} colorama {channel_command}")
    assert len(actual["actions"]) == 3
    for key, val in expected_debug.items():
        if key == "timestamp":
            assert actual["debug"][2][key].startswith(val)
        else:
            assert actual["debug"][2][key] == val

    expected_start = [f"name: {name}", "channels:"]
    for channel in channels:
        expected_start.append(f"  - {channel}")
    expected_history_start = "\n".join(expected_start + [
        "packages:",
        "  conda:",
        "    python: '3.6'",
        "    pytest: '*'",
        "logs:",
        "  - conda create --name end_to_end_test python=3.6 colorama --override-channels --strict-channel-priority",
        "    --channel main",
        f"  - conda install --name {name} pytest",
        f"  - {expected_log}",
        "actions:",
        f"  - conda create --name {name} python=3.6",
    ])

    end = actual_history_content.rfind("python=3.6") + len("python=3.6")
    actual_history_start = actual_history_content[:end]
    assert actual_history_start == expected_history_start
Example #6
0
 def append(self, log: str, action: str):
     """Append to the environment history."""
     self.logs.append(log)
     self.actions.append(action)
     self.debug.update(pip_version=get_pip_version(name=self.name))
Example #7
0
 def create(cls, name: str):
     """Create the class with the first set of debug information."""
     debug = cls()
     debug.update(get_pip_version(name=name))
     return debug
Example #8
0
def test_history_pip_install(pip_setup):
    """Test the history.yaml in detail."""
    name = pip_setup["name"]
    env = pip_setup["env"]
    env_dir = pip_setup["env_dir"]
    channels = pip_setup["channels"]

    history_file = env_dir / "history.yaml"
    actual_history_content = history_file.read_text()
    print(actual_history_content)

    actual = yaml.load(actual_history_content, Loader=yaml.FullLoader)

    pip_action_exp = rf"(pip install pytest==4.0.0)(\s)(pytest-cov==)(.*)(--index-url {pip.PIP_DEFAULT_INDEX_URL})"

    expected_packages = {
        "conda": {"colorama": "*", "python": "python=3.6"},
        "pip": {"pytest": "pytest==4.0.0", "pytest-cov": "*"},
    }
    expected_log = (
        f"pip install pytest==4.0.0 pytest-cov --index-url {pip.PIP_DEFAULT_INDEX_URL}"
    )
    expected_debug = 2 * [
        {
            "platform": get_platform_name(),
            "conda_version": CONDA_VERSION,
            "pip_version": pip.get_pip_version(name=name),
            "timestamp": str(date.today()),
        }
    ]
    assert actual["name"] == name
    assert actual["channels"] == channels
    assert actual["packages"] == expected_packages
    assert actual["revisions"][-1]["log"] == expected_log
    assert len(actual["revisions"]) == 2
    assert re.match(pip_action_exp, actual["revisions"][-1]["action"])
    for i in range(len(actual["revisions"])):
        for key, val in expected_debug[i].items():
            if key == "timestamp":
                assert actual["revisions"][i]["debug"][key].startswith(val)
            else:
                assert actual["revisions"][i]["debug"][key] == val

    # The packages section at the top of the file is current
    expected_packages_section = "\n".join(
        [
            "packages:",
            "  conda:",
            "    python: python=3.6",
            "    colorama: '*'",
            "  pip:",
            "    pytest: pytest==4.0.0",
            "    pytest-cov: '*'",
            "revisions:",
        ]
    )
    assert expected_packages_section in actual_history_content

    pip_dependencies = env.dependencies["pip"]

    expected_second_revision = "\n".join(
        [
            "  - packages:",
            "      conda:",
            "        python: python=3.6",
            "        colorama: '*'",
            "      pip:",
            "        pytest: pytest==4.0.0",
            "        pytest-cov: '*'",
            "    diff:",
            "      pip:",
            "        upsert:",
            "        - pytest==4.0.0",
            f"        - pytest-cov=={pip_dependencies['pytest-cov'].version}",
            f"    log: pip install pytest==4.0.0 pytest-cov --index-url {pip.PIP_DEFAULT_INDEX_URL}",
            f"    action: pip install pytest",
        ]
    )

    index_first_revision = actual_history_content.find("  - packages:")
    index_second_revision_start = actual_history_content.find(
        "  - packages:", index_first_revision + 1
    )
    second_action = "action: pip install pytest"
    index_second_action = actual_history_content.find(
        second_action, index_second_revision_start
    ) + len(second_action)
    actual_second_revision = actual_history_content[
        index_second_revision_start:index_second_action
    ]
    assert actual_second_revision == expected_second_revision
Example #9
0
def test_pip_version():
    name = os.environ.get("CONDA_DEFAULT_ENV")
    if name:
        version = pip.get_pip_version(name=name)
        assert isinstance(version, str)
        assert version >= "18.1"
def test_remove_package(end_to_end_setup):
    """Test the removal of a package."""
    name = end_to_end_setup["name"]
    env_dir = end_to_end_setup["env_dir"]
    channels = end_to_end_setup["channels"]
    channel_command = end_to_end_setup["channel_command"].replace(
        "--strict-channel-priority ", "")

    conda_remove(name=name, specs=["colorama"], yes=True)

    actual_env_content = (env_dir / "environment.yml").read_text()
    assert "colorama" not in actual_env_content

    log_file = env_dir / "history.yaml"
    actual_history_content = log_file.read_text()
    print(actual_history_content)

    actual = yaml.load(actual_history_content, Loader=yaml.FullLoader)

    expected_packages = {
        "conda": {
            "python": "python=3.6",
            "pytest": "pytest>4.0,<6.0"
        }
    }
    expected_log = f"conda remove --name {name} colorama"
    expected_debug = {
        "platform": get_platform_name(),
        "conda_version": CONDA_VERSION,
        "pip_version": get_pip_version(name=name),
        "timestamp": str(date.today()),
    }

    assert actual["packages"] == expected_packages
    assert len(actual["revisions"]) == 3
    assert actual["revisions"][-1]["log"] == expected_log
    assert actual["channels"] == channels
    assert (actual["revisions"][-1]["action"] ==
            f"conda remove --name {name} colorama {channel_command}")
    for key, val in expected_debug.items():
        if key == "timestamp":
            assert actual["revisions"][2]["debug"][key].startswith(val)
        else:
            assert actual["revisions"][2]["debug"][key] == val

    # The packages section at the top of the file is current
    expected_packages_section = "\n".join([
        "packages:",
        "  conda:",
        "    python: python=3.6",
        "    pytest: pytest>4.0,<6.0",
        "revisions:",
    ])
    assert expected_packages_section in actual_history_content

    expected_third_revision = "\n".join([
        "  - packages:",
        "      conda:",
        "        python: python=3.6",
        "        pytest: pytest>4.0,<6.0",
        "    diff:",
        "      conda:",
        "        remove:",
        "        - colorama",
        f"    log: conda remove --name {name} colorama",
        f"    action: conda remove --name {name} colorama",
    ])
    index_first_revision = actual_history_content.find("  - packages:")
    index_second_revision = actual_history_content.find(
        "  - packages:", index_first_revision + 1)
    index_third_revision = actual_history_content.find(
        "  - packages:", index_second_revision + 1)
    third_action = f"    action: {expected_log}"
    index_third_action = actual_history_content.find(
        third_action, index_third_revision) + len(third_action)
    actual_third_revision = actual_history_content[
        index_third_revision:index_third_action]
    assert actual_third_revision == expected_third_revision
def test_history_after_create(end_to_end_setup):
    """Test the history.yaml in detail."""
    name = end_to_end_setup["name"]
    env = end_to_end_setup["env"]
    env_dir = end_to_end_setup["env_dir"]
    channels = end_to_end_setup["channels"]
    channel_command = end_to_end_setup["channel_command"]

    history_file = env_dir / "history.yaml"
    actual_history_content = history_file.read_text()
    print(actual_history_content)

    actual = yaml.load(actual_history_content, Loader=yaml.FullLoader)

    action_expected_pattern = rf"(conda create --name {name})(\s)(python=3.6)(.*)(\s)(colorama=)(.*)({channel_command})"

    expected_packages = {"conda": {"colorama": "*", "python": "python=3.6"}}
    expected_log = f"conda create --name {name} python=3.6 colorama {channel_command}"

    expected_debug = [{
        "platform": get_platform_name(),
        "conda_version": CONDA_VERSION,
        "pip_version": get_pip_version(name=name),
        "timestamp": str(date.today()),
    }]

    assert actual["packages"] == expected_packages
    assert actual["revisions"][-1]["log"] == expected_log
    assert actual["channels"] == channels
    assert re.match(action_expected_pattern, actual["revisions"][0]["action"])
    for key, val in expected_debug[0].items():
        if key == "timestamp":
            assert actual["revisions"][0]["debug"][key].startswith(val)
        else:
            assert actual["revisions"][0]["debug"][key] == val

    conda_dependencies = env.dependencies["conda"]

    expected_start = [
        f"name: {name}",
        f"id: {env.history.id}",
        "history-file-version: '1.0'",
        "channels:",
    ]
    for channel in channels:
        expected_start.append(f"  - {channel}")
    expected_history_start = "\n".join(expected_start + [
        "packages:",
        "  conda:",
        "    python: python=3.6",
        "    colorama: '*'",
        "revisions:",
        "  - packages:",
        "      conda:",
        "        python: python=3.6",
        "        colorama: '*'",
        "    diff:",
        "      conda:",
        "        upsert:",
        f"        - python={conda_dependencies['python'].version}",
        f"        - colorama={conda_dependencies['colorama'].version}",
        f"    log: conda create --name {name} python=3.6 colorama --override-channels",
        "      --strict-channel-priority --channel main",
        f"    action: conda create --name {name} python=3.6",
    ])
    first_action_start = f"action: conda create --name {name} python=3.6"
    index_first_action = actual_history_content.find(first_action_start) + len(
        first_action_start)
    actual_history_start = actual_history_content[:index_first_action]
    assert actual_history_start == expected_history_start
def test_history_after_install(end_to_end_setup):
    """Test the history.yaml file in detail after pytest has been installed."""
    name = end_to_end_setup["name"]

    env = conda_install(name=name, specs=["pytest>4.0,<6.0"], yes=True)

    env_dir = end_to_end_setup["env_dir"]
    channels = end_to_end_setup["channels"]
    channel_command = end_to_end_setup["channel_command"]

    log_file = env_dir / "history.yaml"
    actual_history_content = log_file.read_text()
    print(actual_history_content)

    actual = yaml.load(actual_history_content, Loader=yaml.FullLoader)

    action_install_expected_pattern = (
        rf"(conda install --name {name})(\s)(pytest=)(.*)({channel_command})")

    expected_packages = {
        "conda": {
            "colorama": "*",
            "python": "python=3.6",
            "pytest": "pytest>4.0,<6.0"
        }
    }
    expected_log = f'conda install --name {name} "pytest>4.0,<6.0"'
    expected_debug = 2 * [{
        "platform": get_platform_name(),
        "conda_version": CONDA_VERSION,
        "pip_version": get_pip_version(name=name),
        "timestamp": str(date.today()),
    }]

    assert actual["packages"] == expected_packages
    assert len(actual["revisions"]) == 2
    assert actual["revisions"][-1]["log"] == expected_log
    assert actual["channels"] == channels
    assert re.match(action_install_expected_pattern,
                    actual["revisions"][-1]["action"])
    for key, val in expected_debug[1].items():
        if key == "timestamp":
            assert actual["revisions"][1]["debug"][key].startswith(val)
        else:
            assert actual["revisions"][1]["debug"][key] == val

    # The packages section at the top of the file is current
    expected_packages_section = "\n".join([
        "packages:",
        "  conda:",
        "    python: python=3.6",
        "    colorama: '*'",
        "    pytest: pytest>4.0,<6.0",
        "revisions:",
    ])
    assert expected_packages_section in actual_history_content

    conda_dependencies = env.dependencies["conda"]

    expected_second_revision = "\n".join([
        "  - packages:",
        "      conda:",
        "        python: python=3.6",
        "        colorama: '*'",
        "        pytest: pytest>4.0,<6.0",
        "    diff:",
        "      conda:",
        "        upsert:",
        f"        - pytest={conda_dependencies['pytest'].version}",
        f'    log: conda install --name {name} "pytest>4.0,<6.0"',
        f"    action: conda install --name {name} pytest",
    ])

    index_first_revision = actual_history_content.find("  - packages:")
    index_second_revision_start = actual_history_content.find(
        "  - packages:", index_first_revision + 1)
    second_action = f"action: conda install --name {name} pytest"
    index_second_action = actual_history_content.find(
        second_action, index_second_revision_start) + len(second_action)
    actual_second_revision = actual_history_content[
        index_second_revision_start:index_second_action]
    assert actual_second_revision == expected_second_revision
Example #13
0
def test_history_pip_install(pip_setup):
    """Test the history.yaml in detail."""
    name = pip_setup["name"]
    env_dir = pip_setup["env_dir"]
    channels = pip_setup["channels"]

    history_file = env_dir / "history.yaml"
    actual_history_content = history_file.read_text()
    print(actual_history_content)

    actual = yaml.load(actual_history_content, Loader=yaml.FullLoader)

    pip_action_exp = rf"(pip install pytest==4.0.0)(\s)(pytest-cov==)(.*)(--index-url {pip.PIP_DEFAULT_INDEX_URL})"

    expected_packages = {
        "conda": {"colorama": "*", "python": "3.6"},
        "pip": {"pytest": "4.0.0", "pytest-cov": "*"},
    }
    expected_log = (
        f"pip install pytest==4.0.0 pytest-cov --index-url {pip.PIP_DEFAULT_INDEX_URL}"
    )
    expected_debug = 2 * [
        {
            "platform": get_platform_name(),
            "conda_version": CONDA_VERSION,
            "pip_version": pip.get_pip_version(name=name),
            "timestamp": str(date.today()),
        }
    ]
    assert actual["name"] == name
    assert actual["channels"] == channels
    assert actual["packages"] == expected_packages
    assert actual["logs"][-1] == expected_log
    assert len(actual["logs"]) == 2
    assert re.match(pip_action_exp, actual["actions"][-1])
    assert len(actual["actions"]) == 2
    for i in range(len(actual["debug"])):
        for key, val in expected_debug[i].items():
            if key == "timestamp":
                assert actual["debug"][i][key].startswith(val)
            else:
                assert actual["debug"][i][key] == val

    expected_history = [f"name: {name}", "channels:"]
    for channel in channels:
        expected_history.append(f"  - {channel}")
    expected_history_start = "\n".join(
        expected_history
        + [
            "packages:",
            "  conda:",
            "    python: '3.6'",
            "    colorama: '*'",
            "  pip:",
            "    pytest: 4.0.0",
            "    pytest-cov: '*'",
            "logs:",
            "  - conda create --name end_to_end_test python=3.6 colorama --override-channels --strict-channel-priority",
            "    --channel main",
            f"  - {expected_log}",
            "actions:",
            f"  - conda create --name {name} python=3.6",
        ]
    )
    end = actual_history_content.rfind("python=3.6") + len("python=3.6")
    actual_history_start = actual_history_content[:end]
    assert actual_history_start == expected_history_start
def test_remote_end_to_end(end_to_end_setup, mocker):
    """Test setup, create, install, pull and push feature of conda_env_tracker"""
    env = end_to_end_setup["env"]
    remote_dir = end_to_end_setup["remote_dir"]
    channels = end_to_end_setup["channels"]
    channel_command = end_to_end_setup["channel_command"]

    setup_remote(name=env.name, remote_dir=remote_dir)

    local_io = EnvIO(env_directory=USER_ENVS_DIR / env.name)
    assert str(local_io.get_remote_dir()) == str(remote_dir)
    assert not list(remote_dir.glob("*"))

    push(name=env.name)
    remote_io = EnvIO(env_directory=remote_dir)
    assert remote_io.get_history() == local_io.get_history()
    assert remote_io.get_environment() == local_io.get_environment()

    env = conda_install(name=env.name, specs=["pytest"], yes=True)
    assert env.local_io.get_history() != remote_io.get_history()
    env = push(name=env.name)
    assert env.local_io.get_history() == remote_io.get_history()

    log_mock = mocker.patch("conda_env_tracker.pull.logging.Logger.info")
    env = pull(name=env.name)
    log_mock.assert_called_once_with("Nothing to pull.")

    remove_package_from_history(env, "pytest")

    conda_dependencies = env.dependencies["conda"]
    assert env.local_io.get_history() != remote_io.get_history()
    assert env.history.packages == {
        "conda": {
            "python":
            Package(
                "python",
                "python=3.6",
                version=conda_dependencies["python"].version,
                build=conda_dependencies["python"].build,
            ),
            "colorama":
            Package(
                "colorama",
                "colorama",
                version=conda_dependencies["colorama"].version,
                build=conda_dependencies["colorama"].build,
            ),
        }
    }

    env = pull(name=env.name)

    assert env.local_io.get_history() == remote_io.get_history()
    assert remote_io.get_environment() == local_io.get_environment()

    remove_package_from_history(env, "pytest")
    assert env.local_io.get_history() != remote_io.get_history()

    env = conda_install(name=env.name,
                        specs=["pytest-cov"],
                        channels=("main", ),
                        yes=True)
    env = pull(name=env.name, yes=True)

    conda_dependencies = env.dependencies["conda"]
    assert env.history.packages == {
        "conda": {
            "python":
            Package(
                "python",
                "python=3.6",
                version=conda_dependencies["python"].version,
                build=conda_dependencies["python"].build,
            ),
            "colorama":
            Package(
                "colorama",
                "colorama",
                version=conda_dependencies["colorama"].version,
                build=conda_dependencies["colorama"].build,
            ),
            "pytest":
            Package(
                "pytest",
                "pytest",
                version=conda_dependencies["pytest"].version,
                build=conda_dependencies["pytest"].build,
            ),
            "pytest-cov":
            Package(
                "pytest-cov",
                "pytest-cov",
                version=conda_dependencies["pytest-cov"].version,
                build=conda_dependencies["pytest-cov"].build,
            ),
        }
    }

    log_list = [
        f"conda create --name {env.name} python=3.6 colorama {channel_command}",
        f"conda install --name {env.name} pytest",
        f"conda install --name {env.name} pytest-cov --channel main",
    ]
    assert env.history.logs == log_list

    actual_env = (env.local_io.env_dir / "environment.yml").read_text()
    conda_dependencies = get_dependencies(name=env.name)["conda"]
    expected_env = [f"name: {env.name}", "channels:"]
    for channel in channels + ["nodefaults"]:
        expected_env.append(f"  - {channel}")
    expected_env = ("\n".join(expected_env + [
        "dependencies:",
        "  - python=" + conda_dependencies["python"].version,
        "  - colorama=" + conda_dependencies["colorama"].version,
        "  - pytest=" + conda_dependencies["pytest"].version,
        "  - pytest-cov=" + conda_dependencies["pytest-cov"].version,
    ]) + "\n")
    assert actual_env == expected_env

    expected_debug = 3 * [{
        "platform": get_platform_name(),
        "conda_version": CONDA_VERSION,
        "pip_version": get_pip_version(name=env.name),
        "timestamp": str(date.today()),
    }]
    for i in range(len(env.history.debug)):
        for key, val in expected_debug[i].items():
            if key == "timestamp":
                assert env.history.debug[i][key].startswith(val)
            else:
                assert env.history.debug[i][key] == val
def test_history_r_install(r_setup):
    """Test the history.yaml in detail."""
    # pylint: disable=line-too-long
    name = r_setup["name"]
    env_dir = r_setup["env_dir"]
    channels = r_setup["channels"]

    history_file = env_dir / "history.yaml"
    actual_history_content = history_file.read_text()
    print(actual_history_content)

    actual = yaml.load(actual_history_content, Loader=yaml.FullLoader)

    expected_action = 'R --quiet --vanilla -e \'library("devtools"); install_version("jsonlite", version="1.2"); install.packages("praise")\''

    expected_packages = {
        "conda": {
            "r-base": "*",
            "r-devtools": "*"
        },
        "r": {
            "jsonlite": "1.2",
            "praise": "*"
        },
    }
    expected_log = 'R --quiet --vanilla -e \'library("devtools"); install_version("jsonlite", version="1.2"); install.packages("praise")\''
    expected_debug = 2 * [{
        "platform": get_platform_name(),
        "conda_version": CONDA_VERSION,
        "pip_version": pip.get_pip_version(name=name),
        "timestamp": str(date.today()),
    }]
    assert actual["name"] == name
    assert actual["channels"] == channels
    assert actual["packages"] == expected_packages
    assert actual["logs"][-1] == expected_log
    assert len(actual["logs"]) == 2
    assert actual["actions"][-1] == expected_action
    assert len(actual["actions"]) == 2
    for i in range(len(actual["debug"])):
        for key, val in expected_debug[i].items():
            if key == "timestamp":
                assert actual["debug"][i][key].startswith(val)
            else:
                assert actual["debug"][i][key] == val

    expected_history = [f"name: {name}", "channels:"]
    for channel in channels:
        expected_history.append(f"  - {channel}")
    expected_history_start = "\n".join(expected_history + [
        "packages:",
        "  conda:",
        "    r-base: '*'",
        "    r-devtools: '*'",
        "  r:",
        "    jsonlite: '1.2'",
        "    praise: '*'",
        "logs:",
        "  - conda create --name end_to_end_test r-base r-devtools --override-channels",
        "    --strict-channel-priority",
        "    --channel r --channel defaults",
        "    main",
        '  - R --quiet --vanilla -e \'library("devtools"); install_version("jsonlite", version="1.2");',
        '    install.packages("praise")\'',
        "actions:",
        f"  - conda create --name {name} r-base",
    ])
    end = actual_history_content.rfind("r-base") + len("r-base")
    actual_history_start = actual_history_content[:end]
    assert actual_history_start == expected_history_start