def test_resolve_dependencies_with_actual_conda(): manager = DefaultCondaManager(frontend=NullFrontend()) lock_set = manager.resolve_dependencies(['bokeh'], channels=(), platforms=(conda_api.current_platform(), )) specs = lock_set.package_specs_for_current_platform pprint(specs) names = [conda_api.parse_spec(spec).name for spec in specs] assert 'bokeh' in names assert len(specs) > 5 # 5 is an arbitrary number of deps that surely bokeh has
def test_resolve_dependencies_with_conda_api_mock(monkeypatch): def mock_resolve_dependencies(pkgs, platform, channels): return [('bokeh', '0.12.4', '0'), ('thing', '1.0', '1')] monkeypatch.setattr('anaconda_project.internal.conda_api.resolve_dependencies', mock_resolve_dependencies) manager = DefaultCondaManager(frontend=NullFrontend()) lock_set = manager.resolve_dependencies(['bokeh'], channels=(), platforms=(conda_api.current_platform(), )) assert lock_set.package_specs_for_current_platform == ('bokeh=0.12.4=0', 'thing=1.0=1')
def test_resolve_dependencies_with_conda_api_mock_raises_error(monkeypatch): def mock_resolve_dependencies(pkgs, platform, channels): raise conda_api.CondaError("nope") monkeypatch.setattr('anaconda_project.internal.conda_api.resolve_dependencies', mock_resolve_dependencies) manager = DefaultCondaManager(frontend=NullFrontend()) with pytest.raises(CondaManagerError) as excinfo: manager.resolve_dependencies(['bokeh'], channels=(), platforms=(conda_api.current_platform(), )) assert 'Error resolving for' in str(excinfo.value)
def do_test(dirname): envdir = os.path.join(dirname, spec.name) manager = DefaultCondaManager(frontend=NullFrontend()) deviations = manager.find_environment_deviations(envdir, spec) error = "Env spec 'myenv' does not have the current platform %s in the lock file" % conda_api.current_platform() assert error == deviations.summary with pytest.raises(CondaManagerError) as excinfo: manager.fix_environment_deviations(envdir, spec, deviations=deviations) assert str(excinfo.value).startswith("Unable to update environment at ")
def do_test(dirname): from codecs import open as real_open envdir = os.path.join(dirname, spec.name) manager = DefaultCondaManager(frontend=NullFrontend()) counts = dict(calls=0) def mock_open(*args, **kwargs): counts['calls'] += 1 if counts['calls'] == 1: raise IOError("did not open") else: return real_open(*args, **kwargs) monkeypatch.setattr('codecs.open', mock_open) # this should NOT throw but also should not write the # timestamp file (we ignore errors) filename = manager._timestamp_file(envdir, spec) assert filename.startswith(envdir) assert not os.path.exists(filename) manager._write_timestamp_file(envdir, spec) assert not os.path.exists(filename) # the second time we really wsrite it (this is to prove we # are looking at the right filename) manager._write_timestamp_file(envdir, spec) assert os.path.exists(filename) # check on the file contents with real_open(filename, 'r', encoding='utf-8') as f: content = json.loads(f.read()) assert dict(anaconda_project_version=version) == content
def check(dirname): prefix = os.path.join(dirname, "myenv") os.makedirs(os.path.join(prefix, 'conda-meta')) def mock_installed(prefix): return {'bokeh': ('bokeh', '0.12.4', '1')} monkeypatch.setattr('anaconda_project.internal.conda_api.installed', mock_installed) spec_with_matching_bokeh = EnvSpec(name='myenv', conda_packages=['bokeh=0.12.4=1'], pip_packages=[], channels=[]) spec_with_more_vague_bokeh = EnvSpec(name='myenv', conda_packages=['bokeh=0.12'], pip_packages=[], channels=[]) spec_with_unspecified_bokeh = EnvSpec(name='myenv', conda_packages=['bokeh'], pip_packages=[], channels=[]) spec_with_wrong_version_bokeh = EnvSpec( name='myenv', conda_packages=['bokeh=0.12.3'], pip_packages=[], channels=[]) spec_with_wrong_build_bokeh = EnvSpec( name='myenv', conda_packages=['bokeh=0.12.4=0'], pip_packages=[], channels=[]) manager = DefaultCondaManager(frontend=NullFrontend()) deviations = manager.find_environment_deviations( prefix, spec_with_matching_bokeh) assert deviations.missing_packages == () assert deviations.wrong_version_packages == () deviations = manager.find_environment_deviations( prefix, spec_with_more_vague_bokeh) assert deviations.missing_packages == () assert deviations.wrong_version_packages == () deviations = manager.find_environment_deviations( prefix, spec_with_unspecified_bokeh) assert deviations.missing_packages == () assert deviations.wrong_version_packages == () deviations = manager.find_environment_deviations( prefix, spec_with_wrong_version_bokeh) assert deviations.missing_packages == () assert deviations.wrong_version_packages == ('bokeh', ) deviations = manager.find_environment_deviations( prefix, spec_with_wrong_build_bokeh) assert deviations.missing_packages == () assert deviations.wrong_version_packages == ('bokeh', )
def do_test(dirname): envdir = os.path.join(dirname, spec.name) manager = DefaultCondaManager(frontend=NullFrontend()) def print_timestamps(when): newest_in_prefix = 0 for d in manager._timestamp_comparison_directories(envdir): try: t = os.path.getmtime(d) except Exception: t = 0 if t > newest_in_prefix: newest_in_prefix = t timestamp_fname = manager._timestamp_file(envdir, spec) try: timestamp_file = os.path.getmtime(timestamp_fname) except Exception: timestamp_file = 0 print("%s: timestamp file %d prefix %d diff %g" % (when, timestamp_file, newest_in_prefix, newest_in_prefix - timestamp_file)) print_timestamps("before env creation") assert not os.path.isdir(envdir) assert not os.path.exists(os.path.join(envdir, IPYTHON_BINARY)) assert not os.path.exists(os.path.join(envdir, PYINSTRUMENT_BINARY)) assert not manager._timestamp_file_up_to_date(envdir, spec) deviations = manager.find_environment_deviations(envdir, spec) assert set(deviations.missing_packages) == {'python', 'ipython'} assert deviations.missing_pip_packages == ('pyinstrument', ) assert not deviations.ok manager.fix_environment_deviations(envdir, spec, deviations) print_timestamps("after fixing deviations") assert os.path.isdir(envdir) assert os.path.isdir(os.path.join(envdir, "conda-meta")) assert os.path.exists(os.path.join(envdir, IPYTHON_BINARY)) assert os.path.exists(os.path.join(envdir, PYINSTRUMENT_BINARY)) assert manager._timestamp_file_up_to_date(envdir, spec) called = [] from anaconda_project.internal.pip_api import installed as real_pip_installed from anaconda_project.internal.conda_api import installed as real_conda_installed def traced_pip_installed(*args, **kwargs): called.append(("pip_api.installed", args, kwargs)) return real_pip_installed(*args, **kwargs) monkeypatch.setattr('anaconda_project.internal.pip_api.installed', traced_pip_installed) def trace_conda_installed(*args, **kwargs): called.append(("conda_api.installed", args, kwargs)) return real_conda_installed(*args, **kwargs) monkeypatch.setattr('anaconda_project.internal.conda_api.installed', trace_conda_installed) deviations = manager.find_environment_deviations(envdir, spec) assert [] == called assert deviations.missing_packages == () assert deviations.missing_pip_packages == () assert deviations.ok assert manager._timestamp_file_up_to_date(envdir, spec) # now modify conda-meta and check that we DO call the package managers time.sleep(1.1) # be sure we are in a new second conda_meta_dir = os.path.join(envdir, "conda-meta") print("conda-meta original timestamp: %d" % os.path.getmtime(conda_meta_dir)) inside_conda_meta = os.path.join(conda_meta_dir, "thing.txt") with codecs.open(inside_conda_meta, 'w', encoding='utf-8') as f: f.write(u"This file should change the mtime on conda-meta\n") print("file inside conda-meta %d and conda-meta itself %d" % (os.path.getmtime(inside_conda_meta), os.path.getmtime(conda_meta_dir))) os.remove(inside_conda_meta) print_timestamps("after touching conda-meta") assert not manager._timestamp_file_up_to_date(envdir, spec) deviations = manager.find_environment_deviations(envdir, spec) assert len(called) == 2 assert deviations.missing_packages == () assert deviations.missing_pip_packages == () # deviations should not be ok (due to timestamp) assert not deviations.ok assert not manager._timestamp_file_up_to_date(envdir, spec) # we want to be sure we update the timestamp file even though # there wasn't any actual work to do manager.fix_environment_deviations(envdir, spec, deviations) print_timestamps("after fixing deviations 2") assert manager._timestamp_file_up_to_date(envdir, spec)
def do_test(dirname): from codecs import open as real_open envdir = os.path.join(dirname, spec.name) manager = DefaultCondaManager(frontend=NullFrontend()) is_readonly = dict(readonly=False) def mock_open(*args, **kwargs): if is_readonly['readonly']: raise IOError("did not open") return real_open(*args, **kwargs) monkeypatch.setattr('codecs.open', mock_open) assert not os.path.isdir(envdir) assert not os.path.exists(os.path.join(envdir, IPYTHON_BINARY)) assert not os.path.exists(os.path.join(envdir, FLAKE8_BINARY)) assert not manager._timestamp_file_up_to_date(envdir, spec) deviations = manager.find_environment_deviations(envdir, spec) assert set(deviations.missing_packages) == {'python', 'ipython'} assert deviations.missing_pip_packages == ('pyinstrument', ) # with create=False, we won't create the env with pytest.raises(CondaManagerError) as excinfo: manager.fix_environment_deviations(envdir, spec, deviations, create=False) assert 'does not exist' in str(excinfo.value) assert not os.path.isdir(envdir) # now create the env manager.fix_environment_deviations(envdir, spec, deviations) assert os.path.isdir(envdir) assert os.path.isdir(os.path.join(envdir, "conda-meta")) assert os.path.exists(os.path.join(envdir, IPYTHON_BINARY)) assert os.path.exists(os.path.join(envdir, PYINSTRUMENT_BINARY)) assert manager._timestamp_file_up_to_date(envdir, spec) assert not manager._timestamp_file_up_to_date( envdir, spec_with_phony_pip_package) # test bad pip package throws error deviations = manager.find_environment_deviations( envdir, spec_with_phony_pip_package) assert deviations.missing_packages == () assert deviations.wrong_version_packages == () assert deviations.missing_pip_packages == ('nope_not_a_thing', ) with pytest.raises(CondaManagerError) as excinfo: manager.fix_environment_deviations(envdir, spec_with_phony_pip_package, deviations) assert 'Failed to install missing pip packages' in str(excinfo.value) assert not manager._timestamp_file_up_to_date( envdir, spec_with_phony_pip_package) # test bad url package throws error deviations = manager.find_environment_deviations( envdir, spec_with_bad_url_pip_package) assert deviations.missing_packages == () assert deviations.wrong_version_packages == () assert deviations.missing_pip_packages == ('phony', ) with pytest.raises(CondaManagerError) as excinfo: manager.fix_environment_deviations(envdir, spec_with_bad_url_pip_package, deviations) assert 'Failed to install missing pip packages' in str(excinfo.value) assert not manager._timestamp_file_up_to_date( envdir, spec_with_bad_url_pip_package) # test we notice wrong ipython version AND missing bokeh AND readonly environment is_readonly['readonly'] = True deviations = manager.find_environment_deviations( envdir, spec_with_bokeh_and_old_ipython) assert deviations.missing_packages == ('bokeh', ) assert deviations.wrong_version_packages == ('ipython', ) assert deviations.unfixable is_readonly['readonly'] = False # test we notice only missing bokeh deviations = manager.find_environment_deviations( envdir, spec_with_bokeh) assert deviations.missing_packages == ('bokeh', ) assert deviations.wrong_version_packages == () assert not deviations.unfixable # test we notice wrong ipython version and can downgrade deviations = manager.find_environment_deviations( envdir, spec_with_old_ipython) assert deviations.missing_packages == () assert deviations.wrong_version_packages == ('ipython', ) assert not deviations.unfixable manager.fix_environment_deviations(envdir, spec_with_old_ipython, deviations) assert manager._timestamp_file_up_to_date(envdir, spec_with_old_ipython) deviations = manager.find_environment_deviations( envdir, spec_with_old_ipython) assert deviations.missing_packages == () assert deviations.wrong_version_packages == () # update timestamp; this doesn't re-upgrade because `spec` doesn't # specify an ipython version assert not manager._timestamp_file_up_to_date(envdir, spec) deviations = manager.find_environment_deviations(envdir, spec) assert deviations.missing_packages == () assert deviations.wrong_version_packages == () # fix_environment_deviations should be a no-op on readonly envs # with no deviations, in particular the time stamp file should # not be changed and therefore not be up to date is_readonly['readonly'] = True manager.fix_environment_deviations(envdir, spec, deviations) assert not manager._timestamp_file_up_to_date(envdir, spec) # when the environment is readwrite, the timestamp file should # be updated is_readonly['readonly'] = False manager.fix_environment_deviations(envdir, spec, deviations) assert manager._timestamp_file_up_to_date(envdir, spec) deviations = manager.find_environment_deviations(envdir, spec) assert deviations.missing_packages == () assert deviations.wrong_version_packages == () # test that we can remove a package assert manager._timestamp_file_up_to_date(envdir, spec) time.sleep( 1) # removal is fast enough to break our timestamp resolution manager.remove_packages(prefix=envdir, packages=['ipython']) assert not os.path.exists(os.path.join(envdir, IPYTHON_BINARY)) assert not manager._timestamp_file_up_to_date(envdir, spec) # test for error removing with pytest.raises(CondaManagerError) as excinfo: manager.remove_packages(prefix=envdir, packages=['ipython']) # different versions of conda word this differently message = str(excinfo.value) valid_strings = ('no packages found to remove', 'Package not found', "named 'ipython' found to remove", 'PackagesNotFoundError:', "is missing from the environment") assert any(s in message for s in valid_strings) assert not manager._timestamp_file_up_to_date(envdir, spec) # test failure to exec pip def mock_call_pip(*args, **kwargs): raise pip_api.PipError("pip fail") monkeypatch.setattr('anaconda_project.internal.pip_api._call_pip', mock_call_pip) with pytest.raises(CondaManagerError) as excinfo: deviations = manager.find_environment_deviations(envdir, spec) assert 'pip failed while listing' in str(excinfo.value)
def do_test(dirname): envdir = os.path.join(dirname, spec.name) manager = DefaultCondaManager() assert not os.path.isdir(envdir) assert not os.path.exists(os.path.join(envdir, IPYTHON_BINARY)) assert not os.path.exists(os.path.join(envdir, FLAKE8_BINARY)) assert not manager._timestamp_file_up_to_date(envdir, spec) deviations = manager.find_environment_deviations(envdir, spec) assert deviations.missing_packages == ('ipython', ) assert deviations.missing_pip_packages == ('flake8', ) manager.fix_environment_deviations(envdir, spec, deviations) assert os.path.isdir(envdir) assert os.path.isdir(os.path.join(envdir, "conda-meta")) assert os.path.exists(os.path.join(envdir, IPYTHON_BINARY)) assert os.path.exists(os.path.join(envdir, FLAKE8_BINARY)) assert manager._timestamp_file_up_to_date(envdir, spec) assert not manager._timestamp_file_up_to_date( envdir, spec_with_phony_pip_package) # test bad pip package throws error deviations = manager.find_environment_deviations( envdir, spec_with_phony_pip_package) assert deviations.missing_packages == () assert deviations.missing_pip_packages == ('nope_not_a_thing', ) with pytest.raises(CondaManagerError) as excinfo: manager.fix_environment_deviations(envdir, spec_with_phony_pip_package, deviations) assert 'Failed to install missing pip packages' in str(excinfo.value) assert not manager._timestamp_file_up_to_date( envdir, spec_with_phony_pip_package) # test bad url package throws error deviations = manager.find_environment_deviations( envdir, spec_with_bad_url_pip_package) assert deviations.missing_packages == () assert deviations.missing_pip_packages == ('phony', ) with pytest.raises(CondaManagerError) as excinfo: manager.fix_environment_deviations(envdir, spec_with_bad_url_pip_package, deviations) assert 'Failed to install missing pip packages' in str(excinfo.value) assert not manager._timestamp_file_up_to_date( envdir, spec_with_bad_url_pip_package) # test that we can remove a package assert manager._timestamp_file_up_to_date(envdir, spec) manager.remove_packages(prefix=envdir, packages=['ipython']) assert not os.path.exists(os.path.join(envdir, IPYTHON_BINARY)) assert not manager._timestamp_file_up_to_date(envdir, spec) # test for error removing with pytest.raises(CondaManagerError) as excinfo: manager.remove_packages(prefix=envdir, packages=['ipython']) # different versions of conda word this differently assert 'no packages found to remove' in str( excinfo.value) or 'Package not found' in str(excinfo.value) assert not manager._timestamp_file_up_to_date(envdir, spec) # test failure to exec pip def mock_call_pip(*args, **kwargs): raise pip_api.PipError("pip fail") monkeypatch.setattr('anaconda_project.internal.pip_api._call_pip', mock_call_pip) with pytest.raises(CondaManagerError) as excinfo: deviations = manager.find_environment_deviations(envdir, spec) assert 'pip failed while listing' in str(excinfo.value)
def do_test(dirname): envdir = os.path.join(dirname, spec.name) manager = DefaultCondaManager(frontend=NullFrontend()) assert not os.path.isdir(envdir) assert not os.path.exists(os.path.join(envdir, IPYTHON_BINARY)) assert not os.path.exists(os.path.join(envdir, FLAKE8_BINARY)) assert not manager._timestamp_file_up_to_date(envdir, spec) deviations = manager.find_environment_deviations(envdir, spec) assert deviations.missing_packages == ('ipython', ) assert deviations.missing_pip_packages == ('pyinstrument', ) # with create=False, we won't create the env with pytest.raises(CondaManagerError) as excinfo: manager.fix_environment_deviations(envdir, spec, deviations, create=False) assert 'does not exist' in str(excinfo.value) assert not os.path.isdir(envdir) # now create the env manager.fix_environment_deviations(envdir, spec, deviations) assert os.path.isdir(envdir) assert os.path.isdir(os.path.join(envdir, "conda-meta")) assert os.path.exists(os.path.join(envdir, IPYTHON_BINARY)) assert os.path.exists(os.path.join(envdir, PYINSTRUMENT_BINARY)) assert manager._timestamp_file_up_to_date(envdir, spec) assert not manager._timestamp_file_up_to_date(envdir, spec_with_phony_pip_package) # test bad pip package throws error deviations = manager.find_environment_deviations(envdir, spec_with_phony_pip_package) assert deviations.missing_packages == () assert deviations.wrong_version_packages == () assert deviations.missing_pip_packages == ('nope_not_a_thing', ) with pytest.raises(CondaManagerError) as excinfo: manager.fix_environment_deviations(envdir, spec_with_phony_pip_package, deviations) assert 'Failed to install missing pip packages' in str(excinfo.value) assert not manager._timestamp_file_up_to_date(envdir, spec_with_phony_pip_package) # test bad url package throws error deviations = manager.find_environment_deviations(envdir, spec_with_bad_url_pip_package) assert deviations.missing_packages == () assert deviations.wrong_version_packages == () assert deviations.missing_pip_packages == ('phony', ) with pytest.raises(CondaManagerError) as excinfo: manager.fix_environment_deviations(envdir, spec_with_bad_url_pip_package, deviations) assert 'Failed to install missing pip packages' in str(excinfo.value) assert not manager._timestamp_file_up_to_date(envdir, spec_with_bad_url_pip_package) # test we notice wrong ipython version AND missing bokeh deviations = manager.find_environment_deviations(envdir, spec_with_bokeh_and_old_ipython) assert deviations.missing_packages == ('bokeh', ) assert deviations.wrong_version_packages == ('ipython', ) # test we notice only missing bokeh deviations = manager.find_environment_deviations(envdir, spec_with_bokeh) assert deviations.missing_packages == ('bokeh', ) assert deviations.wrong_version_packages == () # test we notice wrong ipython version and can downgrade deviations = manager.find_environment_deviations(envdir, spec_with_old_ipython) assert deviations.missing_packages == () assert deviations.wrong_version_packages == ('ipython', ) manager.fix_environment_deviations(envdir, spec_with_old_ipython, deviations) assert manager._timestamp_file_up_to_date(envdir, spec_with_old_ipython) deviations = manager.find_environment_deviations(envdir, spec_with_old_ipython) assert deviations.missing_packages == () assert deviations.wrong_version_packages == () # update timestamp; this doesn't re-upgrade because `spec` doesn't # specify an ipython version assert not manager._timestamp_file_up_to_date(envdir, spec) deviations = manager.find_environment_deviations(envdir, spec) assert deviations.missing_packages == () assert deviations.wrong_version_packages == () manager.fix_environment_deviations(envdir, spec, deviations) assert manager._timestamp_file_up_to_date(envdir, spec) deviations = manager.find_environment_deviations(envdir, spec) assert deviations.missing_packages == () assert deviations.wrong_version_packages == () # test that we can remove a package assert manager._timestamp_file_up_to_date(envdir, spec) time.sleep(1) # removal is fast enough to break our timestamp resolution manager.remove_packages(prefix=envdir, packages=['ipython']) assert not os.path.exists(os.path.join(envdir, IPYTHON_BINARY)) assert not manager._timestamp_file_up_to_date(envdir, spec) # test for error removing with pytest.raises(CondaManagerError) as excinfo: manager.remove_packages(prefix=envdir, packages=['ipython']) # different versions of conda word this differently message = str(excinfo.value) valid_strings = ('no packages found to remove', 'Package not found', "named 'ipython' found to remove", "is missing from the environment") assert any(s in message for s in valid_strings) assert not manager._timestamp_file_up_to_date(envdir, spec) # test failure to exec pip def mock_call_pip(*args, **kwargs): raise pip_api.PipError("pip fail") monkeypatch.setattr('anaconda_project.internal.pip_api._call_pip', mock_call_pip) with pytest.raises(CondaManagerError) as excinfo: deviations = manager.find_environment_deviations(envdir, spec) assert 'pip failed while listing' in str(excinfo.value)