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)
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 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
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_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 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
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()
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
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 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
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(), ]
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 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
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)
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_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
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_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
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)
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_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
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_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()
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
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)
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 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
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
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