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
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)
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)
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()
def test_extract_packages_from_logs(spec): """Test parsing the packges from action item""" log = Logs(f"conda install --name test {spec}") packages = log.extract_packages(index=0, packages=Packages.from_specs(spec)) assert packages[0] == Package.from_spec(spec)
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"}]
def test_jupyter_kernel_install_query_user_says_no(mocker): run_mock = mocker.patch( "conda_env_tracker.gateways.jupyter.subprocess.run") run_mock.configure_mock( **{ "return_value.returncode": 0, "return_value.stdout": ("Available kernels:\n" " arl /home/username/.local/share/jupyter/kernels/arl\n" " test-env /home/username/.local/share/jupyter/kernels/test-env\n" " rasterstats /home/username/.local/share/jupyter/kernels/rasterstats" ), }) mocker.patch( "conda_env_tracker.gateways.jupyter.prompt_yes_no", new=mocker.Mock(return_value=False), ) debug_mock = mocker.patch( "conda_env_tracker.gateways.jupyter.logger.debug") jupyter_kernel_install_query(name="myenv", packages=[Package.from_spec("jupyter")]) debug_mock.assert_not_called() assert len(run_mock.call_args_list) == 1
def history_diff(env_name: str, env, env_reader) -> ListLike: """return the difference between history and local environment""" version_diff_pkges: ListLike = [] new_pkges: ListLike = [] missing_pkges: ListLike = [] history_conda_pkges = env_reader.get_environment()["dependencies"] history_conda_pkges_dict = {} for spec in history_conda_pkges: name, package = Package.from_spec(spec) history_conda_pkges_dict[name] = package local_conda_pkges = get_dependencies(name=env_name)["conda"] for name, package in local_conda_pkges.items(): if name in history_conda_pkges_dict: if package.version != history_conda_pkges_dict[name].version: version_diff_pkges.append("-" + name + "=" + history_conda_pkges_dict[name]) version_diff_pkges.append("+" + name + "=" + package.version) else: new_pkges.append("+" + name + "=" + package.version) for package in env.history.packages["conda"]: if package not in local_conda_pkges.keys(): missing_pkges.append("-" + package) return version_diff_pkges, new_pkges, missing_pkges
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
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
def test_jupyter_kernel_install_query_jupyter_not_in_packages(mocker): run_mock = mocker.patch( "conda_env_tracker.gateways.jupyter.subprocess.run") jupyter_kernel_install_query(name="myenv", packages=[Package.from_spec("numpy")]) run_mock.assert_not_called()
def test_strict_channel_priority_update_all(setup_env, use_package, mocker): env = setup_env["env"] env_io = setup_env["env_io"] expected = setup_env["expected"] get_package_mock = setup_env["get_package_mock"] get_package_mock.configure_mock( return_value={ "conda": { "pyspark": Package("pyspark", "pyspark", "2.3.2", "py_36"), "pandas": Package("pandas", "pandas", "0.23", "py_36"), } }) mocker.patch("conda_env_tracker.conda.conda_update_all") expected_packages = copy.deepcopy(expected["packages"]) expected_packages["conda"]["pandas"] = Package.from_spec("pandas") update_all_channel_string = "--override-channels " + " ".join( f"--channel {channel}" for channel in expected["channels"]) if use_package: CondaHandler(env=env).update_all( packages=Packages.from_specs("pyspark"), strict_channel_priority=False) expected_packages["conda"]["pyspark"] = Package.from_spec("pyspark") log = f"conda update --all --name {env.name} pyspark" action = f"conda update --all --name {env.name} pyspark=2.3.2=py_36 {update_all_channel_string}" else: CondaHandler(env=env).update_all(strict_channel_priority=False) log = f"conda update --all --name {env.name}" action = f"conda update --all --name {env.name} {update_all_channel_string}" history = env_io.get_history() expected_logs = expected["logs"].copy() expected_logs.append(log) expected_actions = expected["actions"].copy() expected_actions.append(action) assert history.packages == expected_packages assert history.actions == expected_actions assert history.logs == expected_logs
def test_install_upgrade_version_success(setup_env, mocker): env = setup_env["env"] env_io = setup_env["env_io"] expected = setup_env["expected"] get_package_mock = setup_env["get_package_mock"] get_package_mock.configure_mock( return_value={ "conda": { "numpy": Package("numpy", "numpy", "1.1", "py_36"), "pandas": Package("pandas", "pandas", "0.24", "py_36"), } } ) mocker.patch("conda_env_tracker.conda.conda_install") packages = Packages.from_specs("numpy") CondaHandler(env=env).install(packages=packages) history = env_io.get_history() channel_string = "--override-channels --strict-channel-priority " + " ".join( [f"--channel " + channel for channel in expected["channels"]] ) expected_log = expected["logs"].copy() expected_log.append(f"conda install --name {env.name} numpy") expected_action = expected["actions"].copy() expected_packages = copy.deepcopy(expected["packages"]) expected_packages["conda"]["numpy"] = Package.from_spec("numpy") if expected_packages["conda"]["pandas"].spec_is_name(): expected_action.append( f"conda install --name {env.name} numpy=1.1=py_36 {channel_string}" ) else: expected_packages["conda"]["pandas"] = Package.from_spec("pandas=0.24=py_36") expected_action.append( f"conda install --name {env.name} numpy=1.1=py_36 pandas=0.24=py_36 {channel_string}" ) assert history.packages == expected_packages assert history.logs == expected_log assert history.actions == expected_action
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
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
def test_extract_packages_from_actions(spec): """Test parsing the packges from action item""" action = Actions.create( name="test-extract", specs=[spec], channels=Channels(["conda-forge", "conda-remote"]), ) packages = action.extract_packages(index=0) assert packages[0] == Package.from_spec(spec)
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()
def test_pull_pip(setup_tests): new = Package.from_spec("pytest-pylint==0.13.0") remote_history = setup_tests["remote_history"] remote_history.packages.update_packages(packages=[new], source="pip") remote_history.logs.append(f"pip install {new}") remote_history.actions.append(f"pip install {new}") env = Environment(name="test", history=None) final_env = pull(env=env) assert final_env.history == remote_history
def test_pull_different_actions_with_pip(setup_tests): new = Package.from_spec("pytest-pylint==0.13.0") remote_history = setup_tests["remote_history"] local_history = copy.deepcopy(remote_history) env = Environment(name=local_history.name, history=local_history) remote_history.packages.update_packages(packages=[new], source="pip") remote_history.logs.append(f"pip install {new}") remote_history.actions.append(f"pip install {new}") final_env = pull(env=env) assert final_env.history == remote_history
def test_package_install_with_custom_channel(setup_env, channels, mocker): """The user can specify a list of channels that will override the channel precedence order or they can specify a custom channel that is not previously in the environment's channel list""" env = setup_env["env"] env_io = setup_env["env_io"] expected = setup_env["expected"] get_package_mock = setup_env["get_package_mock"] get_package_mock.configure_mock( return_value={ "conda": { "pyspark": Package("pyspark", "pyspark", "0.21", "py_36"), "pandas": Package("pandas", "pandas", "0.23", "py_36"), } } ) mocker.patch("conda_env_tracker.conda.conda_install") CondaHandler(env=env).install( packages=Packages.from_specs("pyspark"), channels=channels ) history = env_io.get_history() expected_log = expected["logs"].copy() expected_action = expected["actions"].copy() expected_packages = copy.deepcopy(expected["packages"]) expected_packages["conda"]["pyspark"] = Package.from_spec("pyspark") channel_log_string = " ".join(["--channel " + channel for channel in channels]) expected_log.append(f"conda install --name {env.name} pyspark {channel_log_string}") computed_channels = channels.copy() for channel in expected["channels"]: if not channel in computed_channels: computed_channels.append(channel) install_channel_string = ( "--override-channels --strict-channel-priority " + " ".join([f"--channel " + channel for channel in computed_channels]) ) assert history.packages == expected_packages expected_action.append( f"conda install --name {env.name} pyspark=0.21=py_36 {install_channel_string}" ) assert history.actions == expected_action assert history.logs == expected_log
def test_replace_existing_env_success(mocker): mocker.patch("conda_env_tracker.env.delete_conda_environment") mocker.patch("conda_env_tracker.env.prompt_yes_no").return_value = True env_name = "conda_env_tracker-test-create-history" create_cmd = f"conda create --name {env_name} pandas" channels = ["conda-forge", "main"] packages = Packages.from_specs("pandas") action = "pandas=0.23=py_36" mocker.patch( "conda_env_tracker.env.get_all_existing_environment").return_value = [ env_name ] mocker.patch("conda_env_tracker.env.conda_create", mocker.Mock(return_value=create_cmd)) mocker.patch( "conda_env_tracker.env.get_dependencies", mocker.Mock(return_value={ "conda": { "pandas": Package("pandas", "*", "0.23=py_36") }, "pip": {}, }), ) mocker.patch( "conda_env_tracker.history.debug.get_pip_version", mocker.Mock(return_value="18.1"), ) mocker.patch("conda_env_tracker.env.get_conda_channels", mocker.Mock(return_value=channels)) Environment.create(name=env_name, packages=packages) writer = EnvIO(env_directory=USER_ENVS_DIR / env_name) history = writer.get_history() channel_string = "--override-channels --strict-channel-priority " + " ".join( "--channel " + channel for channel in channels) assert history.actions == [ f"conda create --name {env_name} {action} {channel_string}" ] assert history.packages == { "conda": { "pandas": Package.from_spec("pandas") } } assert history.channels == channels assert history.logs == [create_cmd] env_dir = Path(USER_ENVS_DIR) / env_name shutil.rmtree(env_dir)
def test_push(setup): env, push_should_fail = setup if push_should_fail: with pytest.raises(CondaEnvTrackerPushError) as err: push(env=env) assert str(err.value) == PUSH_ERROR_STR.format( remote_dir="~/path/to/remote", local_dir=env.user_envs_dir / "test-push") else: push(env=env) assert env.history.packages == { "conda": { "pandas": Package.from_spec("pandas"), "pytest": Package.from_spec("pytest"), } } assert env.history.logs == [ f"conda create --name {env.name} pandas", f"conda install --name {env.name} pytest", ] assert env.history.actions == [ f"conda create --name {env.name} pandas=0.23=py36", f"conda install --name {env.name} pytest=0.11=py36", ]
def test_jupyter_kernel_install_query_jupyter_cant_get_kernelspec(mocker): run_mock = mocker.patch( "conda_env_tracker.gateways.jupyter.subprocess.run") run_mock.configure_mock(**{ "return_value.returncode": 1, "return_value.stderr": "err" }) debug_mock = mocker.patch( "conda_env_tracker.gateways.jupyter.logger.debug") jupyter_kernel_install_query(name="myenv", packages=[Package.from_spec("jupyter")]) debug_mock.assert_called_once_with( "Error while installing jupyter kernel: err") assert len(run_mock.call_args_list) == 1
def test_pip_install_fail(mocker): name = "env_name" packages = [Package.from_spec("not_an_actual_pip_package")] run_mock = mocker.patch("conda_env_tracker.gateways.pip.subprocess.run") run_mock.configure_mock( **{"return_value.returncode": 1, "return_value.stderr": "error"} ) mocker.patch("os.environ.get", mocker.Mock(return_value=name)) with pytest.raises(PipInstallError) as err: pip.pip_install(name=name, packages=packages) assert ( str(err.value) == "Pip install ['not_an_actual_pip_package'] failed with message: error" )
def test_jupyter_kernel_install_query_success_from_different_env(mocker): run_mock = mocker.patch( "conda_env_tracker.gateways.jupyter.subprocess.run") run_mock.configure_mock( **{ "return_value.returncode": 0, "return_value.stdout": ("Available kernels:\n" " arl /home/username/.local/share/jupyter/kernels/arl\n" " test-env /home/username/.local/share/jupyter/kernels/test-env\n" " rasterstats /home/username/.local/share/jupyter/kernels/rasterstats" ), }) mocker.patch( "conda_env_tracker.gateways.jupyter.prompt_yes_no", new=mocker.Mock(return_value=True), ) mocker.patch( "conda_env_tracker.gateways.jupyter.is_current_conda_env", new=mocker.Mock(return_value=False), ) mocker.patch( "conda_env_tracker.gateways.jupyter.get_conda_activate_command", new=mocker.Mock(return_value="conda activate myenv"), ) debug_mock = mocker.patch( "conda_env_tracker.gateways.jupyter.logger.debug") jupyter_kernel_install_query(name="myenv", packages=[Package.from_spec("jupyter")]) debug_mock.assert_not_called() assert run_mock.call_args_list == [ mocker.call( "conda activate myenv && jupyter kernelspec list", shell=True, stdout=subprocess.PIPE, encoding="UTF-8", ), mocker.call( "conda activate myenv && python -m ipykernel install --name myenv --user", shell=True, stderr=subprocess.PIPE, encoding="UTF-8", ), ]
def parse(cls, history_section: dict): """Parse the history.yaml file.""" diff = cls() for source, sections in history_section.items(): diff[source] = {} for section_name, package_specs in sections.items(): diff[source][section_name] = {} for spec in package_specs: if section_name == "remove" or source == "r": package_name = spec diff[source][section_name][ package_name] = Package.from_spec(package_name) else: package_name, version = Package.separate_spec(spec) diff[source][section_name][package_name] = Package( name=package_name, spec=package_name, version=version) return diff
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
def test_jupyter_kernel_install_query_jupyter_cant_install_kernel(mocker): run_mock = mocker.patch( "conda_env_tracker.gateways.jupyter.subprocess.run", new=mocker.Mock(side_effect=[ mocker.Mock( returncode=0, stdout= ("Available kernels:\n" " arl /home/username/.local/share/jupyter/kernels/arl\n" " test-env /home/username/.local/share/jupyter/kernels/test-env\n" " rasterstats /home/username/.local/share/jupyter/kernels/rasterstats" ), ), mocker.Mock(returncode=1, stderr="another err"), ]), ) debug_mock = mocker.patch( "conda_env_tracker.gateways.jupyter.logger.debug") mocker.patch( "conda_env_tracker.gateways.jupyter.prompt_yes_no", new=mocker.Mock(return_value=True), ) mocker.patch( "conda_env_tracker.gateways.jupyter.is_current_conda_env", new=mocker.Mock(return_value=True), ) jupyter_kernel_install_query(name="myenv", packages=[Package.from_spec("jupyter")]) debug_mock.assert_called_once_with( "Error while installing jupyter kernel: another err") run_mock.assert_called_with( "python -m ipykernel install --name myenv --user", shell=True, stderr=subprocess.PIPE, encoding="UTF-8", ) assert len(run_mock.call_args_list) == 2
def test_install_with_default_version_and_yes_success(setup_env, mocker): env = setup_env["env"] env_io = setup_env["env_io"] expected = setup_env["expected"] initial_conda_packages = setup_env["initial_conda_packages"] get_package_mock = setup_env["get_package_mock"] get_package_mock.configure_mock( return_value={ "conda": { **initial_conda_packages, "pyspark": Package("pyspark", "pyspark", "0.21", "py_36"), } } ) mocker.patch("conda_env_tracker.conda.conda_install") packages = Packages.from_specs("pyspark") CondaHandler(env=env).install(packages=packages) history = env_io.get_history() expected_log = expected["logs"].copy() expected_action = expected["actions"].copy() expected_packages = copy.deepcopy(expected["packages"]) expected_packages["conda"]["pyspark"] = Package.from_spec("pyspark") expected_log.append(f"conda install --name {env.name} pyspark") assert history.packages == expected_packages channel_string = "--override-channels --strict-channel-priority " + " ".join( [f"--channel " + channel for channel in expected["channels"]] ) expected_action.append( f"conda install --name {env.name} pyspark=0.21=py_36 {channel_string}" ) assert history.actions == expected_action assert history.logs == expected_log
def test_install_unexpectedly_removes_package(setup_env, mocker): """Simulating that installing python=3.8 uninstalls pandas and there is no version of pandas available for python 3.8 """ env = setup_env["env"] env_io = setup_env["env_io"] expected = setup_env["expected"] logger_mock = mocker.patch("conda_env_tracker.env.logger.warning") get_package_mock = setup_env["get_package_mock"] get_package_mock.configure_mock( return_value={"conda": {"python": Package("python", "python", "3.8", "py_38")}} ) mocker.patch("conda_env_tracker.conda.conda_install") CondaHandler(env=env).install(packages=Packages.from_specs("python=3.8")) history = env_io.get_history() channel_string = "--override-channels --strict-channel-priority " + " ".join( [f"--channel " + channel for channel in expected["channels"]] ) expected_log = expected["logs"].copy() expected_log.append(f"conda install --name {env.name} python=3.8") expected_action = expected["actions"].copy() expected_action.append( f"conda install --name {env.name} python=3.8=py_38 {channel_string}" ) expected_packages = {"conda": {"python": Package.from_spec("python=3.8")}} assert history.packages == expected_packages assert history.logs == expected_log assert history.actions == expected_action logger_mock.assert_called_once_with( 'Package "pandas" was removed during the last command.' )