diff --git a/anaconda_project/conda_manager.py b/anaconda_project/conda_manager.py index 739f690d..b34a6b2f 100644 --- a/anaconda_project/conda_manager.py +++ b/anaconda_project/conda_manager.py @@ -442,7 +442,7 @@ def supports_current_platform(self): """Whether we have locked deps for the current platform.""" return self.enabled and conda_api.current_platform() in self.platforms - def to_json(self): + def to_json(self, pkg_key=YamlFile.pkg_key): """JSON/YAML version of the lock set.""" yaml_dict = _CommentedMap() @@ -462,7 +462,7 @@ def to_json(self): for package in self._package_specs_by_platform[platform]: packages.append(package) packages_dict[platform] = packages - yaml_dict[YamlFile.pkg_key] = packages_dict + yaml_dict[pkg_key] = packages_dict _block_style_all_nodes(yaml_dict) return yaml_dict diff --git a/anaconda_project/env_spec.py b/anaconda_project/env_spec.py index 775008e3..525ef4b0 100644 --- a/anaconda_project/env_spec.py +++ b/anaconda_project/env_spec.py @@ -390,10 +390,8 @@ def filter_context(items): return True - def to_json(self): + def to_json(self, pkg_key=YamlFile.pkg_key): """Get JSON for an anaconda-project.yml env spec section.""" - pkg_key = YamlFile.pkg_key - # Note that we use _conda_packages (only the packages we # introduce ourselves) rather than conda_packages # (includes inherited packages). @@ -411,9 +409,9 @@ def to_json(self): template_json = ryaml.load(""" something: description: null - packages: [] + : [] channels: [] -""".replace('packages', pkg_key), +""".replace('', pkg_key), Loader=ryaml.RoundTripLoader) if self._description is not None: diff --git a/anaconda_project/internal/cli/test/test_command_commands.py b/anaconda_project/internal/cli/test/test_command_commands.py index 79abd361..70d9acfc 100644 --- a/anaconda_project/internal/cli/test/test_command_commands.py +++ b/anaconda_project/internal/cli/test/test_command_commands.py @@ -193,7 +193,7 @@ def mock_console_input(prompt): with_directory_contents_completing_project_file({DEFAULT_PROJECT_FILENAME: ''}, check_ask_type) -def test_add_command_specifying_notebook(monkeypatch, capsys): +def test_add_command_specifying_notebook(monkeypatch, capsys, pkg_key): def check_specifying_notebook(dirname): args = Args('notebook', 'test', 'file.ipynb', directory=dirname) res = main(args) @@ -206,11 +206,11 @@ def check_specifying_notebook(dirname): assert command['env_spec'] == 'default' assert len(command.keys()) == 2 - with_directory_contents_completing_project_file({DEFAULT_PROJECT_FILENAME: 'packages:\n - notebook\n'}, + with_directory_contents_completing_project_file({DEFAULT_PROJECT_FILENAME: f'{pkg_key}:\n - notebook\n'}, check_specifying_notebook) -def test_add_command_guessing_notebook(monkeypatch, capsys): +def test_add_command_guessing_notebook(monkeypatch, capsys, pkg_key): def check_guessing_notebook(dirname): args = Args(None, 'test', 'file.ipynb', directory=dirname) res = main(args) @@ -225,7 +225,7 @@ def check_guessing_notebook(dirname): with_directory_contents_completing_project_file( { - DEFAULT_PROJECT_FILENAME: 'packages:\n - notebook\n', + DEFAULT_PROJECT_FILENAME: f'{pkg_key}:\n - notebook\n', 'file.ipynb': "{}" }, check_guessing_notebook) @@ -332,7 +332,7 @@ def test_remove_command_with_project_file_problems(capsys, monkeypatch): append_dir=True) -def test_remove_command(monkeypatch, capsys): +def test_remove_command(monkeypatch, capsys, pkg_key): def check(dirname): code = _parse_args_and_run_subcommand(['anaconda-project', 'remove-command', 'test', '--directory', dirname]) assert code == 0 @@ -347,7 +347,7 @@ def check(dirname): assert err == '' with_directory_contents_completing_project_file( - {DEFAULT_PROJECT_FILENAME: 'packages: ["notebook"]\ncommands:\n test:\n notebook: file.ipynb\n'}, check) + {DEFAULT_PROJECT_FILENAME: f'{pkg_key}: ["notebook"]\ncommands:\n test:\n notebook: file.ipynb\n'}, check) def test_remove_command_missing(monkeypatch, capsys): @@ -378,7 +378,7 @@ def check_empty_project(dirname): with_directory_contents_completing_project_file({DEFAULT_PROJECT_FILENAME: ""}, check_empty_project) -def test_list_commands(capsys): +def test_list_commands(capsys, pkg_key): def check_empty_project(dirname): code = _parse_args_and_run_subcommand(['anaconda-project', 'list-commands', '--directory', dirname]) assert code == 0 @@ -404,13 +404,13 @@ def check_empty_project(dirname): " bokeh_app: test.py\n" " run_notebook:\n" " notebook: test.ipynb\n" - "packages:\n" + f"{pkg_key}:\n" " - bokeh\n" " - notebook\n") }, check_empty_project) -def test_list_default_command(capsys): +def test_list_default_command(capsys, pkg_key): def check_empty_project(dirname): code = _parse_args_and_run_subcommand(['anaconda-project', 'list-default-command', '--directory', dirname]) assert code == 0 @@ -426,7 +426,7 @@ def check_empty_project(dirname): " bokeh_app: test.py\n" " 0second:\n" " notebook: test.ipynb\n" - "packages:\n" + f"{pkg_key}:\n" " - bokeh\n" " - notebook\n") }, check_empty_project) diff --git a/anaconda_project/internal/cli/test/test_environment_commands.py b/anaconda_project/internal/cli/test/test_environment_commands.py index 113db068..a3d30331 100644 --- a/anaconda_project/internal/cli/test/test_environment_commands.py +++ b/anaconda_project/internal/cli/test/test_environment_commands.py @@ -164,7 +164,7 @@ def check(dirname): with_directory_contents_completing_project_file(dict(), check) -def test_remove_env_spec_fails(capsys, monkeypatch): +def test_remove_env_spec_fails(capsys, monkeypatch, pkg_key): def check(dirname): from shutil import rmtree as real_rmtree _monkeypatch_pwd(monkeypatch, dirname) @@ -192,13 +192,22 @@ def mock_remove(path, ignore_errors=False, onerror=None): with_directory_contents_completing_project_file( { - DEFAULT_PROJECT_FILENAME: 'env_specs:\n foo:\n channels: []\n packages:\n - bar\n' + - ' baz:\n channels: []\n packages:\n - bar\n', + DEFAULT_PROJECT_FILENAME: """ +env_specs: + foo: + channels: [] + : + - bar + baz: + channels: [] + : + - bar +""".replace('', pkg_key), 'envs/foo/bin/test': 'code here' }, check) -def test_remove_env_spec(capsys, monkeypatch): +def test_remove_env_spec(capsys, monkeypatch, pkg_key): def check(dirname): _monkeypatch_pwd(monkeypatch, dirname) @@ -212,13 +221,22 @@ def check(dirname): with_directory_contents_completing_project_file( { - DEFAULT_PROJECT_FILENAME: 'env_specs:\n foo:\n channels: []\n packages:\n - bar\n' + - ' bar:\n channels: []\n packages:\n - baz\n', + DEFAULT_PROJECT_FILENAME: """ +env_specs: + foo: + channels: [] + : + - bar + bar: + channels: [] + : + - baz +""".replace('', pkg_key), 'envs/foo/bin/test': 'code here' }, check) -def test_remove_only_env_spec(capsys, monkeypatch): +def test_remove_only_env_spec(capsys, monkeypatch, pkg_key): def check(dirname): _monkeypatch_pwd(monkeypatch, dirname) @@ -231,12 +249,18 @@ def check(dirname): with_directory_contents_completing_project_file( { - DEFAULT_PROJECT_FILENAME: 'env_specs:\n foo:\n channels: []\n packages:\n - bar\n', + DEFAULT_PROJECT_FILENAME: """ +env_specs: + foo: + channels: [] + : + - bar +""".replace('', pkg_key), 'envs/foo/bin/test': 'code here' }, check) -def test_remove_env_spec_in_use(capsys, monkeypatch): +def test_remove_env_spec_in_use(capsys, monkeypatch, pkg_key): def check(dirname): _monkeypatch_pwd(monkeypatch, dirname) @@ -258,12 +282,12 @@ def check(dirname): env_specs: other: - packages: + : - hello bar: - packages: + : - boo -""", +""".replace('', pkg_key), 'envs/foo/bin/test': 'code here' }, check) @@ -278,7 +302,7 @@ def test_remove_env_spec_with_project_file_problems(capsys, monkeypatch): ['anaconda-project', 'remove-env-spec', '--name', 'foo']) -def test_export_env_spec(capsys, monkeypatch): +def test_export_env_spec(capsys, monkeypatch, pkg_key): def check(dirname): _monkeypatch_pwd(monkeypatch, dirname) @@ -292,13 +316,22 @@ def check(dirname): with_directory_contents_completing_project_file( { - DEFAULT_PROJECT_FILENAME: 'env_specs:\n foo:\n channels: []\n packages:\n - bar\n' + - ' bar:\n channels: []\n packages:\n - baz\n', + DEFAULT_PROJECT_FILENAME: """ +env_specs: + foo: + channels: [] + : + - bar + bar: + channels: [] + : + - baz +""".replace('', pkg_key), 'envs/foo/bin/test': 'code here' }, check) -def test_export_env_spec_default_name(capsys, monkeypatch): +def test_export_env_spec_default_name(capsys, monkeypatch, pkg_key): def check(dirname): _monkeypatch_pwd(monkeypatch, dirname) @@ -312,13 +345,22 @@ def check(dirname): with_directory_contents_completing_project_file( { - DEFAULT_PROJECT_FILENAME: 'env_specs:\n foo:\n channels: []\n packages:\n - bar\n' + - ' bar:\n channels: []\n packages:\n - baz\n', + DEFAULT_PROJECT_FILENAME: """ +env_specs: + foo: + channels: [] + : + - bar + bar: + channels: [] + : + - baz +""".replace('', pkg_key), 'envs/foo/bin/test': 'code here' }, check) -def test_export_env_spec_no_filename(capsys, monkeypatch): +def test_export_env_spec_no_filename(capsys, monkeypatch, pkg_key): def check(dirname): _monkeypatch_pwd(monkeypatch, dirname) @@ -331,8 +373,17 @@ def check(dirname): with_directory_contents_completing_project_file( { - DEFAULT_PROJECT_FILENAME: 'env_specs:\n foo:\n channels: []\n packages:\n - bar\n' + - ' bar:\n channels: []\n packages:\n - baz\n', + DEFAULT_PROJECT_FILENAME: """ +env_specs: + foo: + channels: [] + : + - bar + bar: + channels: [] + : + - baz +""".replace('', pkg_key), 'envs/foo/bin/test': 'code here' }, check) @@ -384,7 +435,7 @@ def check(dirname): with_directory_contents_completing_project_file(dict(), check) -def test_add_packages_to_specific_environment(capsys, monkeypatch): +def test_add_packages_to_specific_environment(capsys, monkeypatch, pkg_key): def check(dirname): _monkeypatch_pwd(monkeypatch, dirname) params = _monkeypatch_add_packages(monkeypatch, SimpleStatus(success=True, description='Installed ok.')) @@ -404,9 +455,9 @@ def check(dirname): {DEFAULT_PROJECT_FILENAME: """ env_specs: foo: - packages: + : - bar -"""}, check) +""".replace('', pkg_key)}, check) def test_add_pip_packages_to_specific_environment(capsys, monkeypatch): @@ -426,12 +477,14 @@ def check(dirname): assert dict(env_spec_name='foo', packages=['a', 'b'], channels=None, pip=True) == params['kwargs'] with_directory_contents_completing_project_file( - {DEFAULT_PROJECT_FILENAME: """ + { + DEFAULT_PROJECT_FILENAME: """ env_specs: foo: - packages: + : - bar -"""}, check) +""" + }, check) def test_remove_packages_from_all_environments(capsys, monkeypatch): @@ -498,7 +551,7 @@ def check(dirname): with_directory_contents_completing_project_file(dict(), check) -def test_add_platforms_to_specific_environment(capsys, monkeypatch): +def test_add_platforms_to_specific_environment(capsys, monkeypatch, pkg_key): def check(dirname): _monkeypatch_pwd(monkeypatch, dirname) params = _monkeypatch_add_platforms(monkeypatch, SimpleStatus(success=True, description='Installed ok.')) @@ -514,12 +567,14 @@ def check(dirname): assert dict(env_spec_name='foo', platforms=['a', 'b']) == params['kwargs'] with_directory_contents_completing_project_file( - {DEFAULT_PROJECT_FILENAME: """ + { + DEFAULT_PROJECT_FILENAME: """ env_specs: foo: - packages: + : - bar -"""}, check) +""".replace('', pkg_key) + }, check) def test_remove_platforms_from_all_environments(capsys, monkeypatch): @@ -558,7 +613,7 @@ def check(dirname): with_directory_contents_completing_project_file(dict(), check) -def test_list_environments(capsys, monkeypatch): +def test_list_environments(capsys, monkeypatch, pkg_key): def check_list_not_empty(dirname): code = _parse_args_and_run_subcommand(['anaconda-project', 'list-env-specs', '--directory', dirname]) @@ -577,13 +632,15 @@ def check_list_not_empty(dirname): with_directory_contents_completing_project_file( { - DEFAULT_PROJECT_FILENAME: ('env_specs:\n' - ' foo:\n' - ' packages:\n' - ' - bar\n' - ' bar:\n' - ' packages:\n' - ' - bar\n') + DEFAULT_PROJECT_FILENAME: """ +env_specs: + foo: + : + - bar + bar: + : + - bar +""".replace('', pkg_key) }, check_list_not_empty) @@ -629,7 +686,7 @@ def check_missing_env(dirname): with_directory_contents_completing_project_file({DEFAULT_PROJECT_FILENAME: ""}, check_missing_env) -def _test_list_packages(capsys, env, expected_conda_deps, expected_pip_deps): +def _test_list_packages(capsys, env, expected_conda_deps, expected_pip_deps, pkg_key): def check_list_not_empty(dirname): params = ['anaconda-project', 'list-packages', '--directory', dirname] if env is not None: @@ -648,30 +705,34 @@ def check_list_not_empty(dirname): expected_pip_deps) assert out == expected_out - project_contents = ('env_specs:\n' - ' foo:\n' - ' packages:\n' - ' - requests\n' - ' - flask\n' - ' bar:\n' - ' packages:\n' - ' - httplib\n' - ' - django\n\n' - 'packages:\n' - ' - mandatory_package\n' - ' - pip:\n' - ' - mandatory_pip_package\n') + project_contents = """ +env_specs: + foo: + : + - requests + - flask + bar: + : + - httplib + - django\n +: + - mandatory_package + - pip: + - mandatory_pip_package""".replace('', pkg_key) with_directory_contents_completing_project_file({DEFAULT_PROJECT_FILENAME: project_contents}, check_list_not_empty) -def test_list_packages_from_env(capsys): - _test_list_packages(capsys, 'bar', '\ndjango\nhttplib\nmandatory_package\n\n', '\nmandatory_pip_package\n\n') - _test_list_packages(capsys, 'foo', '\nflask\nmandatory_package\nrequests\n\n', '\nmandatory_pip_package\n\n') +def test_list_packages_from_env(capsys, pkg_key): + _test_list_packages(capsys, 'bar', '\ndjango\nhttplib\nmandatory_package\n\n', + '\nmandatory_pip_package\n\n', pkg_key=pkg_key) + _test_list_packages(capsys, 'foo', '\nflask\nmandatory_package\nrequests\n\n', + '\nmandatory_pip_package\n\n', pkg_key=pkg_key) -def test_list_packages_from_env_default(capsys): - _test_list_packages(capsys, None, '\nflask\nmandatory_package\nrequests\n\n', '\nmandatory_pip_package\n\n') +def test_list_packages_from_env_default(capsys, pkg_key): + _test_list_packages(capsys, None, '\nflask\nmandatory_package\nrequests\n\n', + '\nmandatory_pip_package\n\n', pkg_key=pkg_key) def test_list_packages_with_project_file_problems(capsys, monkeypatch): diff --git a/anaconda_project/internal/cli/test/test_prepare.py b/anaconda_project/internal/cli/test/test_prepare.py index d11e6ca5..fd998fe2 100644 --- a/anaconda_project/internal/cli/test/test_prepare.py +++ b/anaconda_project/internal/cli/test/test_prepare.py @@ -116,7 +116,8 @@ def main_redis_url(dirname): assert "All ports from 6380 to 6449 were in use" in err -def test_prepare_command_choose_environment(capsys, monkeypatch): +#@pytest._change_default_pkg_key +def test_prepare_command_choose_environment(capsys, monkeypatch, pkg_key): def mock_conda_create(prefix, pkgs, channels, stdout_callback, stderr_callback): from anaconda_project.internal.makedirs import makedirs_ok_if_exists metadir = os.path.join(prefix, "conda-meta") @@ -142,16 +143,15 @@ def check_prepare_choose_environment(dirname): with_directory_contents_completing_project_file( { - DEFAULT_PROJECT_FILENAME: - """ + DEFAULT_PROJECT_FILENAME: """ env_specs: foo: - packages: + : - nonexistent_foo bar: - packages: + : - nonexistent_bar -""" +""".replace("", pkg_key) }, check_prepare_choose_environment) out, err = capsys.readouterr() @@ -160,7 +160,7 @@ def check_prepare_choose_environment(dirname): assert err == "" -def test_prepare_command_all_environments(capsys, monkeypatch): +def test_prepare_command_all_environments(capsys, monkeypatch, pkg_key): def mock_conda_create(prefix, pkgs, channels, stdout_callback, stderr_callback): from anaconda_project.internal.makedirs import makedirs_ok_if_exists metadir = os.path.join(prefix, "conda-meta") @@ -188,16 +188,15 @@ def check_prepare_choose_environment(dirname): with_directory_contents_completing_project_file( { - DEFAULT_PROJECT_FILENAME: - """ + DEFAULT_PROJECT_FILENAME: """ env_specs: foo: - packages: + : - nonexistent_foo bar: - packages: + : - nonexistent_bar -""" +""".replace("", pkg_key) }, check_prepare_choose_environment) out, err = capsys.readouterr() @@ -206,7 +205,7 @@ def check_prepare_choose_environment(dirname): assert err == "" -def test_prepare_command_all_environments_refresh(capsys, monkeypatch): +def test_prepare_command_all_environments_refresh(capsys, monkeypatch, pkg_key): def mock_conda_create(prefix, pkgs, channels, stdout_callback, stderr_callback): from anaconda_project.internal.makedirs import makedirs_ok_if_exists metadir = os.path.join(prefix, "conda-meta") @@ -238,16 +237,15 @@ def check_prepare_choose_environment(dirname): with_directory_contents_completing_project_file( { - DEFAULT_PROJECT_FILENAME: - """ + DEFAULT_PROJECT_FILENAME: """ env_specs: foo: - packages: + : - nonexistent_foo bar: - packages: + : - nonexistent_bar -""" +""".replace("", pkg_key) }, check_prepare_choose_environment) out, err = capsys.readouterr() @@ -258,7 +256,7 @@ def check_prepare_choose_environment(dirname): assert err == "" -def test_prepare_command_default_environment_refresh(capsys, monkeypatch): +def test_prepare_command_default_environment_refresh(capsys, monkeypatch, pkg_key): def mock_conda_create(prefix, pkgs, channels, stdout_callback, stderr_callback): from anaconda_project.internal.makedirs import makedirs_ok_if_exists metadir = os.path.join(prefix, "conda-meta") @@ -285,9 +283,9 @@ def check_prepare_choose_environment(dirname): assert os.path.isfile(foo_package_json) with_directory_contents_completing_project_file({DEFAULT_PROJECT_FILENAME: """ -packages: +: - nonexistent_foo -"""}, check_prepare_choose_environment) +""".replace("", pkg_key)}, check_prepare_choose_environment) out, err = capsys.readouterr() assert out == ("The project is ready to run commands.\n" + @@ -297,7 +295,7 @@ def check_prepare_choose_environment(dirname): assert err == "" -def test_prepare_command_choose_environment_does_not_exist(capsys): +def test_prepare_command_choose_environment_does_not_exist(capsys, pkg_key): def check_prepare_choose_environment_does_not_exist(dirname): project_dir_disable_dedicated_env(dirname) result = _parse_args_and_run_subcommand( @@ -312,21 +310,20 @@ def check_prepare_choose_environment_does_not_exist(dirname): with_directory_contents_completing_project_file( { - DEFAULT_PROJECT_FILENAME: - """ + DEFAULT_PROJECT_FILENAME: """ env_specs: foo: - packages: + : - nonexistent_foo bar: - packages: + : - nonexistent_bar -""" +""".replace("", pkg_key) }, check_prepare_choose_environment_does_not_exist) @pytest.mark.slow -def test_prepare_command_choose_command_chooses_env_spec(capsys): +def test_prepare_command_choose_command_chooses_env_spec(capsys, pkg_key): def check(dirname): project_dir_disable_dedicated_env(dirname) result = _parse_args_and_run_subcommand( @@ -347,14 +344,13 @@ def check(dirname): with_directory_contents_completing_project_file( { - DEFAULT_PROJECT_FILENAME: - """ + DEFAULT_PROJECT_FILENAME: """ env_specs: foo: - packages: + : - nonexistent_foo bar: - packages: + : - nonexistent_bar commands: with_foo: @@ -364,7 +360,7 @@ def check(dirname): conda_app_entry: python --version env_spec: bar -""" +""".replace("", pkg_key) }, check) @@ -605,7 +601,7 @@ def mock_console_input(prompt, encrypted): @pytest.mark.slow -def test_no_ask_conda_prefix_interactively(monkeypatch, capsys): +def test_no_ask_conda_prefix_interactively(monkeypatch, capsys, pkg_key): def check(dirname): project_dir_disable_dedicated_env(dirname) @@ -628,12 +624,12 @@ def mock_console_input(prompt, encrypted): with_directory_contents_completing_project_file( {DEFAULT_PROJECT_FILENAME: """ -packages: +: - nonexistent_package_name -"""}, check) +""".replace("", pkg_key)}, check) -def test_display_suggestions(monkeypatch, capsys): +def test_display_suggestions(monkeypatch, capsys, pkg_key): def check(dirname): project_dir_disable_dedicated_env(dirname) @@ -661,6 +657,6 @@ def mock_console_input(prompt, encrypted): assert '' == err with_directory_contents_completing_project_file({DEFAULT_PROJECT_FILENAME: """ -packages: [] +: [] weird_field: 42 -"""}, check) +""".replace("", pkg_key)}, check) diff --git a/anaconda_project/project.py b/anaconda_project/project.py index 050a5fba..abeb987c 100644 --- a/anaconda_project/project.py +++ b/anaconda_project/project.py @@ -841,7 +841,8 @@ def set_env_spec_platforms(project): prompt = "Overwrite env spec %s with the changes from %s?" % (importable_spec.name, importable_filename) def overwrite_env_spec_from_importable(project): - project.project_file.set_value(['env_specs', importable_spec.name], importable_spec.to_json()) + project.project_file.set_value(['env_specs', importable_spec.name], + importable_spec.to_json(pkg_key=project.pkg_key)) def remember_no_import_importable(project): project.project_file.set_value(['skip_imports', 'environment'], importable_spec.logical_hash) @@ -862,7 +863,8 @@ def remember_no_import_importable(project): # import, above. def add_default_env_spec(project): default_spec = _anaconda_default_env_spec(self.global_base_env_spec) - project.project_file.set_value(['env_specs', default_spec.name], default_spec.to_json()) + project.project_file.set_value(['env_specs', default_spec.name], + default_spec.to_json(pkg_key=project.pkg_key)) # This section should now be inaccessible # since env_spec will be added at runtime if missing @@ -1202,6 +1204,10 @@ def load_default_specs(): assert isinstance(frontend, Frontend) self._frontends = [frontend] + @property + def pkg_key(self): + return self.project_file.pkg_key + def _updated_cache(self): self._config_cache.update(self._project_file, self._lock_file) return self._config_cache diff --git a/anaconda_project/project_file.py b/anaconda_project/project_file.py index 9cac5880..aee485fe 100644 --- a/anaconda_project/project_file.py +++ b/anaconda_project/project_file.py @@ -92,7 +92,7 @@ class ProjectFile(YamlFile): # before your code runs. # Use `anaconda-project add-packages` to add packages. # -packages: [] +: [] # # In the channels section, list any Conda channel URLs to be searched @@ -119,7 +119,7 @@ class ProjectFile(YamlFile): # Use `anaconda-project add-env-spec` to add environment specs. # env_specs: {} -''' +'''.replace('', YamlFile.pkg_key) @classmethod def load_for_directory(cls, directory, default_env_specs_func=_empty_default_env_spec, scan_parents=True): @@ -190,7 +190,7 @@ def _fill_default_content(self, as_json): default_env_specs = self._default_env_specs_func() assert default_env_specs is not None for env_spec in default_env_specs: - as_json['env_specs'][env_spec.name] = env_spec.to_json() + as_json['env_specs'][env_spec.name] = env_spec.to_json(pkg_key=self.pkg_key) if len(default_env_specs) == 1: # if there's only one env spec, keep it for name/description @@ -204,8 +204,8 @@ def move_list_elements(src, dest): dest.extend(src) del src[:] - if 'packages' in spec_json: - move_list_elements(spec_json['packages'], as_json['packages']) + if self.pkg_key in spec_json: + move_list_elements(spec_json[self.pkg_key], as_json[self.pkg_key]) if 'channels' in spec_json: move_list_elements(spec_json['channels'], as_json['channels']) if 'platforms' in spec_json: diff --git a/anaconda_project/project_lock_file.py b/anaconda_project/project_lock_file.py index e1197240..39fc3c45 100644 --- a/anaconda_project/project_lock_file.py +++ b/anaconda_project/project_lock_file.py @@ -136,7 +136,7 @@ def _set_lock_set(self, env_spec_name, lock_set, all_names): single_env['locked'] = False # now set up the one env - as_json = lock_set.to_json() + as_json = lock_set.to_json(pkg_key=self.pkg_key) self.set_value(['env_specs', env_spec_name], as_json) def _add_pip_packages(self, env_spec_name, pip_packages): diff --git a/anaconda_project/requirements_registry/providers/test/test_conda_env.py b/anaconda_project/requirements_registry/providers/test/test_conda_env.py index 1f57e7d4..707b8ac1 100644 --- a/anaconda_project/requirements_registry/providers/test/test_conda_env.py +++ b/anaconda_project/requirements_registry/providers/test/test_conda_env.py @@ -178,7 +178,7 @@ def prepare_project_scoped_env_not_attempted(dirname): @pytest.mark.slow -def test_prepare_project_scoped_env_with_packages(monkeypatch): +def test_prepare_project_scoped_env_with_packages(monkeypatch, pkg_key): monkeypatch_conda_not_to_use_links(monkeypatch) def prepare_project_scoped_env_with_packages(dirname): @@ -222,16 +222,15 @@ def prepare_project_scoped_env_with_packages(dirname): with_directory_contents_completing_project_file( { - DEFAULT_PROJECT_FILENAME: - """ -packages: + DEFAULT_PROJECT_FILENAME: """ +: - python=3.7 - ipython - numpy=1.15 - pip - pip: - flake8 -""" +""".replace('', pkg_key) }, prepare_project_scoped_env_with_packages) @@ -301,7 +300,7 @@ def check(dirname): with_directory_contents_completing_project_file(dict(), check) -def test_configure_different_env_spec(monkeypatch): +def test_configure_different_env_spec(monkeypatch, pkg_key): def mock_conda_create(prefix, pkgs, channels, stdout_callback, stderr_callback): from anaconda_project.internal.makedirs import makedirs_ok_if_exists metadir = os.path.join(prefix, "conda-meta") @@ -342,19 +341,18 @@ def check(dirname): with_directory_contents_completing_project_file( { - DEFAULT_PROJECT_FILENAME: - """ + DEFAULT_PROJECT_FILENAME: """ env_specs: default: - packages: [] + : [] channels: [] foo: - packages: [] + : [] channels: [] bar: - packages: [] + : [] channels: [] -""" +""".replace('', pkg_key) }, check) @@ -378,7 +376,7 @@ def _readonly_env(env_name, packages): @pytest.mark.slow @pytest.mark.skipif(platform.system() == 'Windows', reason='Windows has a hard time with read-only directories') -def test_clone_readonly_environment_with_deviations(monkeypatch): +def test_clone_readonly_environment_with_deviations(monkeypatch, pkg_key): def clone_readonly_and_prepare(dirname): with _readonly_env(env_name='default', packages=('python=3.7', )) as ro_prefix: readonly = conda_api.installed(ro_prefix) @@ -403,17 +401,17 @@ def clone_readonly_and_prepare(dirname): with_directory_contents_completing_project_file( {DEFAULT_PROJECT_FILENAME: """ -packages: +: - python=3.7 - requests env_specs: default: {} -"""}, clone_readonly_and_prepare) +""".replace('', pkg_key)}, clone_readonly_and_prepare) @pytest.mark.slow @pytest.mark.skipif(platform.system() == 'Windows', reason='Windows has a hard time with read-only directories') -def test_replace_readonly_environment_with_deviations(monkeypatch): +def test_replace_readonly_environment_with_deviations(monkeypatch, pkg_key): def replace_readonly_and_prepare(dirname): with _readonly_env(env_name='default', packages=('python=3.7', )) as ro_prefix: readonly = conda_api.installed(ro_prefix) @@ -438,17 +436,17 @@ def replace_readonly_and_prepare(dirname): with_directory_contents_completing_project_file( {DEFAULT_PROJECT_FILENAME: """ -packages: +: - python=3.7 - requests env_specs: default: {} -"""}, replace_readonly_and_prepare) +""".replace('', pkg_key)}, replace_readonly_and_prepare) @pytest.mark.slow @pytest.mark.skipif(platform.system() == 'Windows', reason='Windows has a hard time with read-only directories') -def test_fail_readonly_environment_with_deviations_unset_policy(monkeypatch): +def test_fail_readonly_environment_with_deviations_unset_policy(monkeypatch, pkg_key): def clone_readonly_and_prepare(dirname): with _readonly_env(env_name='default', packages=('python=3.7', )) as ro_prefix: readonly = conda_api.installed(ro_prefix) @@ -466,17 +464,17 @@ def clone_readonly_and_prepare(dirname): with_directory_contents_completing_project_file( {DEFAULT_PROJECT_FILENAME: """ -packages: +: - python=3.7 - requests env_specs: default: {} -"""}, clone_readonly_and_prepare) +""".replace('', pkg_key)}, clone_readonly_and_prepare) @pytest.mark.slow @pytest.mark.skipif(platform.system() == 'Windows', reason='Windows has a hard time with read-only directories') -def test_fail_readonly_environment_with_deviations_set_policy(monkeypatch): +def test_fail_readonly_environment_with_deviations_set_policy(monkeypatch, pkg_key): def clone_readonly_and_prepare(dirname): with _readonly_env(env_name='default', packages=('python=3.7', )) as ro_prefix: readonly = conda_api.installed(ro_prefix) @@ -496,9 +494,9 @@ def clone_readonly_and_prepare(dirname): with_directory_contents_completing_project_file( {DEFAULT_PROJECT_FILENAME: """ -packages: +: - python=3.7 - requests env_specs: default: {} -"""}, clone_readonly_and_prepare) +""".replace('', pkg_key)}, clone_readonly_and_prepare) diff --git a/anaconda_project/test/test_env_spec.py b/anaconda_project/test/test_env_spec.py index 2e2fa1c9..ad1e8386 100644 --- a/anaconda_project/test/test_env_spec.py +++ b/anaconda_project/test/test_env_spec.py @@ -250,7 +250,7 @@ def test_find_out_of_sync_does_not_exist(): assert name is None -def test_to_json(): +def test_to_json(pkg_key): # the stuff from this parent env spec should NOT end up in the JSON hi = EnvSpec(name="hi", conda_packages=['q', 'r'], @@ -265,19 +265,19 @@ def test_to_json(): channels=['x', 'y'], inherit_from_names=('hi', ), inherit_from=(hi, )) - json = spec.to_json() + json = spec.to_json(pkg_key=pkg_key) assert { 'description': "The Foo Spec", 'channels': ['x', 'y'], 'inherit_from': 'hi', - 'packages': ['a', 'b', { + pkg_key: ['a', 'b', { 'pip': ['c', 'd'] }] } == json -def test_to_json_no_description_no_pip_no_inherit(): +def test_to_json_no_description_no_pip_no_inherit(pkg_key): # should be able to jsonify a spec with no description spec = EnvSpec(name="foo", conda_packages=['a', 'b'], @@ -285,23 +285,23 @@ def test_to_json_no_description_no_pip_no_inherit(): channels=['x', 'y'], inherit_from_names=(), inherit_from=()) - json = spec.to_json() + json = spec.to_json(pkg_key=pkg_key) - assert {'channels': ['x', 'y'], 'packages': ['a', 'b']} == json + assert {'channels': ['x', 'y'], pkg_key: ['a', 'b']} == json -def test_to_json_multiple_inheritance(): +def test_to_json_multiple_inheritance(pkg_key): spec = EnvSpec(name="foo", conda_packages=['a', 'b'], pip_packages=['c', 'd'], channels=['x', 'y'], inherit_from_names=('hi', 'hello')) - json = spec.to_json() + json = spec.to_json(pkg_key=pkg_key) assert { 'channels': ['x', 'y'], 'inherit_from': ['hi', 'hello'], - 'packages': ['a', 'b', { + pkg_key: ['a', 'b', { 'pip': ['c', 'd'] }] } == json diff --git a/anaconda_project/test/test_project.py b/anaconda_project/test/test_project.py index 6e541371..17fffb80 100644 --- a/anaconda_project/test/test_project.py +++ b/anaconda_project/test/test_project.py @@ -241,7 +241,7 @@ def check_problem(dirname): """}, check_problem) -def test_problem_empty_names(packages): +def test_problem_empty_names(pkg_key): def check_problem(dirname): project = project_no_dedicated_env(dirname) @@ -265,7 +265,7 @@ def _fn(s): ' ': redis env_specs: ' ': - {packages}: + {pkg_key}: - python commands: ' ': @@ -473,7 +473,7 @@ def check_set_icon(dirname): }, check_set_icon) -def test_get_package_requirements_from_project_file(packages): +def test_get_package_requirements_from_project_file(pkg_key): def check_get_packages(dirname): project = project_no_dedicated_env(dirname) env = project.env_specs['default'] @@ -499,7 +499,7 @@ def check_get_packages(dirname): with_directory_contents_completing_project_file( { DEFAULT_PROJECT_FILENAME: f""" -{packages}: +{pkg_key}: - foo - hello >= 1.0 - world @@ -524,31 +524,31 @@ def check_get_packages(dirname): with_directory_contents_completing_project_file({DEFAULT_PROJECT_FILENAME: ""}, check_get_packages) -def test_complain_about_packages_not_a_list(packages): +def test_complain_about_packages_not_a_list(pkg_key): def check_get_packages(dirname): project = project_no_dedicated_env(dirname) assert 1 == len(project.problems) "should be a list of strings not" in project.problems[0] with_directory_contents_completing_project_file({DEFAULT_PROJECT_FILENAME: f""" -{packages}: +{pkg_key}: foo: bar """}, check_get_packages) -def test_complain_about_pip_deps_not_a_list(packages): +def test_complain_about_pip_deps_not_a_list(pkg_key): def check(dirname): project = project_no_dedicated_env(dirname) assert 1 == len(project.problems) "should be a list of strings not" in project.problems[0] with_directory_contents_completing_project_file({DEFAULT_PROJECT_FILENAME: f""" -{packages}: +{pkg_key}: - pip: bar """}, check) -def test_complain_about_pip_deps_not_a_string(packages): +def test_complain_about_pip_deps_not_a_string(pkg_key): def check(dirname): project = project_no_dedicated_env(dirname) assert 1 == len(project.problems) @@ -556,13 +556,13 @@ def check(dirname): with_directory_contents_completing_project_file( {DEFAULT_PROJECT_FILENAME: """ -packages: +: - pip: - {} - """.replace('packages', packages)}, check) + """.replace('', pkg_key)}, check) -def test_complain_about_packages_bad_spec(packages): +def test_complain_about_packages_bad_spec(pkg_key): def check_get_packages(dirname): project = project_no_dedicated_env(dirname) filename = project.project_file.basename @@ -574,7 +574,7 @@ def check_get_packages(dirname): with_directory_contents_completing_project_file( {DEFAULT_PROJECT_FILENAME: f""" -{packages}: +{pkg_key}: - "=" - foo bar - pip: @@ -619,7 +619,7 @@ def check_complain_about_conda_env_var(dirname): @pytest._change_default_pkg_key -def test_load_environments(packages): +def test_load_environments(pkg_key): def check_environments(dirname): project = project_no_dedicated_env(dirname) assert 0 == len(project.problems) @@ -688,7 +688,7 @@ def check_environments(dirname): with_directory_contents_completing_project_file( { DEFAULT_PROJECT_FILENAME: """ -packages: +: - global1=1.0 - global2=1.0 channels: @@ -697,7 +697,7 @@ def check_environments(dirname): env_specs: foo: description: "THE FOO" - packages: + : - python - dog - cat @@ -705,7 +705,7 @@ def check_environments(dirname): bar: {} foo_child: inherit_from: foo - packages: + : - dog=2.0 - global1=2.0 - lion @@ -714,7 +714,7 @@ def check_environments(dirname): channels: - abc mixin: - packages: + : - bunny - walrus=1.0 - global2=2.0 @@ -724,18 +724,18 @@ def check_environments(dirname): - hbo foo_grandchild: inherit_from: [foo_child, mixin] - packages: + : - walrus=2.0 - dog=3.0 - pip: - seahorse channels: - nbc - """.replace('packages', packages) + """.replace('', pkg_key) }, check_environments) -def test_load_environments_merging_in_global(packages): +def test_load_environments_merging_in_global(pkg_key): def check_environments(dirname): project = project_no_dedicated_env(dirname) assert 0 == len(project.problems) @@ -757,7 +757,7 @@ def check_environments(dirname): with_directory_contents_completing_project_file( { DEFAULT_PROJECT_FILENAME: """ -packages: +: - dead-parrot - elephant @@ -766,7 +766,7 @@ def check_environments(dirname): env_specs: foo: - packages: + : - python - dog - cat @@ -775,11 +775,11 @@ def check_environments(dirname): - hbo bar: {} default: - packages: + : - lion channels: - cartoons - """.replace('packages', packages) + """.replace('', pkg_key) }, check_environments) @@ -847,14 +847,14 @@ def check_environments(dirname): """}, check_environments) -def test_complain_about_packages_list_of_wrong_thing(packages): +def test_complain_about_packages_list_of_wrong_thing(pkg_key): def check_get_packages(dirname): project = project_no_dedicated_env(dirname) assert 1 == len(project.problems) "should be a string not '42'" in project.problems[0] with_directory_contents_completing_project_file({DEFAULT_PROJECT_FILENAME: f""" -{packages}: +{pkg_key}: - 42 """}, check_get_packages) @@ -1196,7 +1196,7 @@ def check(dirname): check) -def test_command_with_custom_description(packages): +def test_command_with_custom_description(pkg_key): def check(dirname): project = project_no_dedicated_env(dirname) assert [] == project.problems @@ -1207,7 +1207,7 @@ def check(dirname): with_directory_contents_completing_project_file( { DEFAULT_PROJECT_FILENAME: - f"commands:\n default:\n bokeh_app: test.py\n description: hi\n{packages}:\n - bokeh\n" + f"commands:\n default:\n bokeh_app: test.py\n description: hi\n{pkg_key}:\n - bokeh\n" }, check) @@ -1585,7 +1585,7 @@ def check(dirname): {DEFAULT_PROJECT_FILENAME: "commands:\n default:\n notebook: test.ipynb\n"}, check) -def test_notebook_guess_command(packages): +def test_notebook_guess_command(pkg_key): def check_notebook_guess_command(dirname): project = project_no_dedicated_env(dirname) @@ -1616,7 +1616,7 @@ def check_notebook_guess_command(dirname): with_directory_contents_completing_project_file( { DEFAULT_PROJECT_FILENAME: - f"commands:\n default:\n unix: echo 'pass'\nservices:\n REDIS_URL: redis\n{packages}: ['notebook']\n", + f"commands:\n default:\n unix: echo 'pass'\nservices:\n REDIS_URL: redis\n{pkg_key}: ['notebook']\n", 'test.ipynb': '{}', 'envs/should_ignore_this.ipynb': '{}', 'services/should_ignore_this.ipynb': '{}', @@ -1627,7 +1627,7 @@ def check_notebook_guess_command(dirname): # anaconda-project run data.ipynb -def test_notebook_guess_command_can_be_default(packages): +def test_notebook_guess_command_can_be_default(pkg_key): def check_notebook_guess_command_can_be_default(dirname): project = project_no_dedicated_env(dirname) @@ -1648,7 +1648,7 @@ def check_notebook_guess_command_can_be_default(dirname): with_directory_contents_completing_project_file( { - DEFAULT_PROJECT_FILENAME: f"{packages}: ['notebook']\n", + DEFAULT_PROJECT_FILENAME: f"{pkg_key}: ['notebook']\n", # we pick the first command alphabetically in this case # so the test looks for that 'a.ipynb': '{}', @@ -1685,7 +1685,7 @@ def mock_find_executable(*args, **kwargs): {DEFAULT_PROJECT_FILENAME: "commands:\n default:\n notebook: test.ipynb\n"}, check_notebook_command) -def test_multiple_notebooks_suggestion_rejected(packages): +def test_multiple_notebooks_suggestion_rejected(pkg_key): def check(dirname): project = project_no_dedicated_env(dirname) @@ -1709,7 +1709,7 @@ def check(dirname): with_directory_contents_completing_project_file( { DEFAULT_PROJECT_FILENAME: - f"commands:\n default:\n unix: echo 'pass'\nservices:\n REDIS_URL: redis\n{packages}: ['notebook']\n", + f"commands:\n default:\n unix: echo 'pass'\nservices:\n REDIS_URL: redis\n{pkg_key}: ['notebook']\n", 'test.ipynb': '{}', 'foo/test2.ipynb': '{}', 'envs/should_ignore_this.ipynb': 'pretend this is more notebook data', @@ -1719,7 +1719,7 @@ def check(dirname): }, check) -def test_skip_all_notebook_imports(packages): +def test_skip_all_notebook_imports(pkg_key): def check(dirname): project = project_no_dedicated_env(dirname) @@ -1735,12 +1735,12 @@ def check(dirname): with_directory_contents_completing_project_file( { DEFAULT_PROJECT_FILENAME: - f"commands:\n default:\n unix: echo 'pass'\nservices:\n REDIS_URL: redis\n{packages}: ['notebook']\n", + f"commands:\n default:\n unix: echo 'pass'\nservices:\n REDIS_URL: redis\n{pkg_key}: ['notebook']\n", 'test.ipynb': '{}' }, check) -def test_invalid_skip_imports_notebooks(packages): +def test_invalid_skip_imports_notebooks(pkg_key): def check(dirname): project = project_no_dedicated_env(dirname) assert 1 == len(project.problems) @@ -1755,14 +1755,14 @@ def check(dirname): unix: echo 'pass' services: REDIS_URL: redis -packages: ['notebook'] +: ['notebook'] skip_imports: notebooks: {} -""".replace('packages', packages) +""".replace('', pkg_key) }, check) -def test_single_notebook_suggestion_rejected(packages): +def test_single_notebook_suggestion_rejected(pkg_key): def check(dirname): project = project_no_dedicated_env(dirname) @@ -1784,7 +1784,7 @@ def check(dirname): with_directory_contents_completing_project_file( { DEFAULT_PROJECT_FILENAME: - f"commands:\n default:\n unix: echo 'pass'\nservices:\n REDIS_URL: redis\n{packages}: ['notebook']\n", + f"commands:\n default:\n unix: echo 'pass'\nservices:\n REDIS_URL: redis\n{pkg_key}: ['notebook']\n", 'test.ipynb': '{}', 'envs/should_ignore_this.ipynb': 'pretend this is more notebook data', 'services/should_ignore_this.ipynb': 'pretend this is more notebook data', @@ -2320,7 +2320,7 @@ def check_run_with_stuff_missing(dirname): @pytest._change_default_pkg_key -def test_get_publication_info_from_empty_project(packages): +def test_get_publication_info_from_empty_project(pkg_key): def check_publication_info_from_empty(dirname): project = project_no_dedicated_env(dirname) expected = { @@ -2332,7 +2332,7 @@ def check_publication_info_from_empty(dirname): 'env_specs': { 'default': { 'channels': [], - packages: [], + pkg_key: [], 'description': 'Default', 'locked': False, 'platforms': [], @@ -2373,7 +2373,7 @@ def check_publication_info_from_empty(dirname): notebook: foo.ipynb registers_fusion_function: true -packages: +: - foo channels: @@ -2382,17 +2382,17 @@ def check_publication_info_from_empty(dirname): env_specs: default: description: "Default" - packages: + : - notebook woot: - packages: + : - blah - bokeh channels: - woohoo w00t: description: "double 0" - packages: + : - something lol: {} @@ -2409,7 +2409,7 @@ def check_publication_info_from_empty(dirname): """ -def test_get_publication_info_from_complex_project(packages): +def test_get_publication_info_from_complex_project(pkg_key): def check_publication_info_from_complex(dirname): project = project_no_dedicated_env(dirname) @@ -2454,7 +2454,7 @@ def check_publication_info_from_complex(dirname): 'env_specs': { 'default': { 'channels': ['bar'], - f'{packages}': ['foo', 'notebook'], + f'{pkg_key}': ['foo', 'notebook'], 'description': 'Default', 'locked': False, 'platforms': ['linux-64', 'osx-64', 'win-64'], @@ -2490,7 +2490,7 @@ def check_publication_info_from_complex(dirname): }, 'lol': { 'channels': ['bar'], - packages: ['foo'], + pkg_key: ['foo'], 'description': 'lol', 'locked': False, 'platforms': ['linux-64', 'osx-64', 'win-64'], @@ -2526,7 +2526,7 @@ def check_publication_info_from_complex(dirname): }, 'w00t': { 'channels': ['bar'], - packages: ['foo', 'something'], + pkg_key: ['foo', 'something'], 'description': 'double 0', 'locked': False, 'platforms': ['linux-64', 'osx-64', 'win-64'], @@ -2562,7 +2562,7 @@ def check_publication_info_from_complex(dirname): }, 'woot': { 'channels': ['bar', 'woohoo'], - packages: ['foo', 'blah', 'bokeh'], + pkg_key: ['foo', 'blah', 'bokeh'], 'description': 'woot', 'locked': False, 'platforms': ['linux-64', 'osx-64', 'win-64'], @@ -2604,13 +2604,13 @@ def check_publication_info_from_complex(dirname): with_directory_contents_completing_project_file( { - DEFAULT_PROJECT_FILENAME: _complicated_project_contents.replace('packages', packages), + DEFAULT_PROJECT_FILENAME: _complicated_project_contents.replace('', pkg_key), "main.py": "", "foo.ipynb": "" }, check_publication_info_from_complex) -def test_find_requirements(packages): +def test_find_requirements(pkg_key): def check_find_requirements(dirname): project = project_no_dedicated_env(dirname) assert [] == project.problems @@ -2639,13 +2639,13 @@ def check_find_requirements(dirname): with_directory_contents_completing_project_file( { - DEFAULT_PROJECT_FILENAME: _complicated_project_contents.replace('packages', packages), + DEFAULT_PROJECT_FILENAME: _complicated_project_contents.replace('', pkg_key), "main.py": "", "foo.ipynb": "" }, check_find_requirements) -def test_requirements_subsets(packages): +def test_requirements_subsets(pkg_key): def check_requirements_subsets(dirname): project = project_no_dedicated_env(dirname) assert [] == project.problems @@ -2671,13 +2671,13 @@ def check_requirements_subsets(dirname): with_directory_contents_completing_project_file( { - DEFAULT_PROJECT_FILENAME: _complicated_project_contents.replace('packages', packages), + DEFAULT_PROJECT_FILENAME: _complicated_project_contents.replace('', pkg_key), "main.py": "", "foo.ipynb": "" }, check_requirements_subsets) -def test_env_var_name_list_properties(packages): +def test_env_var_name_list_properties(pkg_key): def check_env_var_name_list_properties(dirname): project = project_no_dedicated_env(dirname) assert [] == project.problems @@ -2697,7 +2697,7 @@ def check_env_var_name_list_properties(dirname): with_directory_contents_completing_project_file( { - DEFAULT_PROJECT_FILENAME: _complicated_project_contents.replace('packages', packages), + DEFAULT_PROJECT_FILENAME: _complicated_project_contents.replace('', pkg_key), "main.py": "", "foo.ipynb": "" }, check_env_var_name_list_properties) @@ -2806,7 +2806,7 @@ def check(dirname): }, check) -def test_auto_fix_env_spec_out_of_sync(packages): +def test_auto_fix_env_spec_out_of_sync(pkg_key): def check(dirname): project = project_no_dedicated_env(dirname) assert len(project.problems) == 1 @@ -2816,7 +2816,6 @@ def check(dirname): assert ("Environment spec 'stuff' from environment.yml is out of sync with anaconda-project.yml. Diff:\n" + " channels:\n + bar\n+ a\n+ b\n pip:\n + foo") == problem.text assert problem.can_fix - problem.fix(project) project.project_file.save() @@ -2831,9 +2830,9 @@ def check(dirname): { DEFAULT_PROJECT_FILENAME: """ name: foo -env_specs: { 'stuff': { 'packages':[] } } +env_specs: { 'stuff': { '':[] } } platforms: [linux-32,linux-64,osx-64,win-32,win-64] -""".lstrip().replace("packages", packages), +""".lstrip().replace('', pkg_key), "environment.yml": """ name: stuff @@ -2848,7 +2847,7 @@ def check(dirname): }, check) -def test_auto_fix_env_spec_import_saying_no(packages): +def test_auto_fix_env_spec_import_saying_no(pkg_key): def check(dirname): project = project_no_dedicated_env(dirname) assert len(project.problems) == 1 @@ -2872,9 +2871,9 @@ def check(dirname): { DEFAULT_PROJECT_FILENAME: """ name: foo -env_specs: {'default':{'packages':[]}} +env_specs: {'default':{'':[]}} platforms: [linux-32,linux-64,osx-64,win-32,win-64] -""".lstrip().replace("packages", packages), +""".lstrip().replace('', pkg_key), "environment.yml": """ name: stuff dependencies: @@ -2889,7 +2888,7 @@ def check(dirname): @pytest._change_default_pkg_key -def test_no_auto_fix_env_spec_with_notebook_bokeh_injection(packages): +def test_no_auto_fix_env_spec_with_notebook_bokeh_injection(pkg_key): def check(dirname): project = project_no_dedicated_env(dirname) assert len(project.problems) == 1 @@ -2911,9 +2910,9 @@ def check(dirname): assert spec.channels == ('bar', ) # add bokeh and notebook, which we should ignore - the_packages = project.project_file.get_value(['env_specs', 'stuff', packages]) + the_packages = project.project_file.get_value(['env_specs', 'stuff', pkg_key]) the_packages.extend(['bokeh', 'notebook']) - project.project_file.set_value(['env_specs', 'stuff', packages], the_packages) + project.project_file.set_value(['env_specs', 'stuff', pkg_key], the_packages) project.project_file.save() # no problems despite the diff @@ -2922,17 +2921,17 @@ def check(dirname): assert spec.conda_packages == ('a', 'b', 'bokeh', 'notebook') # add some other package, should NOT ignore - the_packages = project.project_file.get_value(['env_specs', 'stuff', packages]) + the_packages = project.project_file.get_value(['env_specs', 'stuff', pkg_key]) the_packages.extend(['someother']) - project.project_file.set_value(['env_specs', 'stuff', packages], the_packages) + project.project_file.set_value(['env_specs', 'stuff', pkg_key], the_packages) project.project_file.save() assert len(project.problems) == 1 # remove that again - the_packages = project.project_file.get_value(['env_specs', 'stuff', packages]) + the_packages = project.project_file.get_value(['env_specs', 'stuff', pkg_key]) the_packages.remove('someother') - project.project_file.set_value(['env_specs', 'stuff', packages], the_packages) + project.project_file.set_value(['env_specs', 'stuff', pkg_key], the_packages) project.project_file.save() assert len(project.problems) == 0 @@ -2956,7 +2955,7 @@ def check(dirname): assert len(project.problems) == 0 # add a pip package, should NOT ignore - the_packages = project.project_file.get_value(['env_specs', 'stuff', packages]) + the_packages = project.project_file.get_value(['env_specs', 'stuff', pkg_key]) pip_list = None for p in the_packages: if isinstance(p, dict): @@ -2973,9 +2972,9 @@ def check(dirname): { DEFAULT_PROJECT_FILENAME: """ name: foo -env_specs: { 'stuff': { 'packages':[] } } +env_specs: { 'stuff': { '':[] } } platforms: [linux-32,linux-64,osx-64,win-32,win-64] -""".lstrip().replace("packages", packages), +""".lstrip().replace('', pkg_key), "environment.yml": """ name: stuff @@ -3022,7 +3021,7 @@ def check(dirname): }, check) -def test_no_auto_fix_notebook_dep_if_we_have_anaconda(packages): +def test_no_auto_fix_notebook_dep_if_we_have_anaconda(pkg_key): def check(dirname): project = project_no_dedicated_env(dirname) @@ -3032,7 +3031,7 @@ def check(dirname): with_directory_contents_completing_project_file( { - DEFAULT_PROJECT_FILENAME: (f'{packages}:\n' + DEFAULT_PROJECT_FILENAME: (f'{pkg_key}:\n' ' - anaconda\n' 'commands:\n' ' foo.ipynb:\n' @@ -3042,7 +3041,7 @@ def check(dirname): }, check) -def test_no_auto_fix_notebook_dep_if_we_have_notebook(packages): +def test_no_auto_fix_notebook_dep_if_we_have_notebook(pkg_key): def check(dirname): project = project_no_dedicated_env(dirname) @@ -3051,7 +3050,7 @@ def check(dirname): with_directory_contents_completing_project_file( { - DEFAULT_PROJECT_FILENAME: (f'{packages}:\n' + DEFAULT_PROJECT_FILENAME: (f'{pkg_key}:\n' ' - notebook\n' 'commands:\n' ' foo.ipynb:\n' @@ -3113,7 +3112,7 @@ def check(dirname): {DEFAULT_PROJECT_FILENAME: "commands:\n foo:\n unix: something\n somejunk: True\n"}, check) -def test_unknown_field_in_env_spec(packages): +def test_unknown_field_in_env_spec(pkg_key): def check(dirname): project = project_no_dedicated_env(dirname) assert [] == project.problems @@ -3121,10 +3120,10 @@ def check(dirname): assert [expected_suggestion] == project.suggestions with_directory_contents_completing_project_file( - {DEFAULT_PROJECT_FILENAME: f"env_specs:\n foo:\n {packages}: [something]\n somejunk: True\n"}, check) + {DEFAULT_PROJECT_FILENAME: f"env_specs:\n foo:\n {pkg_key}: [something]\n somejunk: True\n"}, check) -def test_unknown_field_in_env_spec_allowed(packages): +def test_unknown_field_in_env_spec_allowed(pkg_key): def check(dirname): project = project_no_dedicated_env(dirname) assert [] == project.problems @@ -3133,7 +3132,7 @@ def check(dirname): with_directory_contents_completing_project_file( { DEFAULT_PROJECT_FILENAME: - f"env_specs:\n foo:\n {packages}: [something]\n somejunk: True\n user_fields: [somejunk]\n" + f"env_specs:\n foo:\n {pkg_key}: [something]\n somejunk: True\n user_fields: [somejunk]\n" }, check) @@ -3174,7 +3173,7 @@ def check(dirname): with_directory_contents({DEFAULT_PROJECT_FILENAME: ""}, check) -def test_with_one_locked_env_spec_has_problems(packages): +def test_with_one_locked_env_spec_has_problems(pkg_key): def check(dirname): project = project_no_dedicated_env(dirname) assert [ @@ -3187,7 +3186,7 @@ def check(dirname): DEFAULT_PROJECT_FILENAME: f""" env_specs: foo: - {packages}: [] + {pkg_key}: [] """, DEFAULT_PROJECT_LOCK_FILENAME: "locking_enabled: true\n" }, check) @@ -3207,19 +3206,19 @@ def check(dirname): }, check) -def test_with_locking_disabled_no_platforms_required(packages): +def test_with_locking_disabled_no_platforms_required(pkg_key): def check(dirname): project = project_no_dedicated_env(dirname) assert [] == project.problems with_directory_contents( { - DEFAULT_PROJECT_FILENAME: f"name: foo\nenv_specs:\n default:\n {packages}: []\n", + DEFAULT_PROJECT_FILENAME: f"name: foo\nenv_specs:\n default:\n {pkg_key}: []\n", DEFAULT_PROJECT_LOCK_FILENAME: "locking_enabled: false\n" }, check) -def test_load_weird_platform(packages): +def test_load_weird_platform(pkg_key): def check(dirname): project = project_no_dedicated_env(dirname) @@ -3242,12 +3241,12 @@ def check(dirname): platforms: [linux-64, weird-valid, weirdinvalid] env_specs: default: - {packages}: [foo] + {pkg_key}: [foo] """ }, check) -def test_only_some_env_specs_have_platforms_locking_disabled(packages): +def test_only_some_env_specs_have_platforms_locking_disabled(pkg_key): def check(dirname): project = project_no_dedicated_env(dirname) assert [] == project.problems @@ -3260,14 +3259,14 @@ def check(dirname): env_specs: default: platforms: [linux-64] - {packages}: [foo] + {pkg_key}: [foo] no_platforms: - {packages}: [bar] + {pkg_key}: [bar] """ }, check) -def test_only_some_env_specs_have_platforms_locking_enabled(packages): +def test_only_some_env_specs_have_platforms_locking_enabled(pkg_key): def check(dirname): project = project_no_dedicated_env(dirname) assert [("anaconda-project.yml: Env spec no_platforms does not have anything in its " + "'platforms:' field.") @@ -3281,9 +3280,9 @@ def check(dirname): env_specs: default: platforms: [linux-64] - {packages}: [foo] + {pkg_key}: [foo] no_platforms: - {packages}: [bar] + {pkg_key}: [bar] """, DEFAULT_PROJECT_LOCK_FILENAME: "locking_enabled: true\n" }, check) @@ -3370,10 +3369,10 @@ def check(dirname): @pytest._change_default_pkg_key -def test_lock_file_non_dict_lock_set_packages(packages): +def test_lock_file_non_dict_lock_set_packages(pkg_key): def check(dirname): project = project_no_dedicated_env(dirname) - expected_error = (f"%s: '{packages}:' section in env spec 'default' in lock file should be a dictionary, " + + expected_error = (f"%s: '{pkg_key}:' section in env spec 'default' in lock file should be a dictionary, " + "found %r") % (project.lock_file.basename, 42) assert [expected_error] == project.problems @@ -3381,12 +3380,12 @@ def check(dirname): {DEFAULT_PROJECT_LOCK_FILENAME: f""" env_specs: default: - {packages}: 42 + {pkg_key}: 42 """}, check) @pytest._change_default_pkg_key -def test_lock_file_has_pip_packages(packages): +def test_lock_file_has_pip_packages(pkg_key): def check(dirname): project = project_no_dedicated_env(dirname) assert [] == project.problems @@ -3401,7 +3400,7 @@ def check(dirname): env_specs: default: platforms: [linux-64,osx-64,win-64] - {packages}: + {pkg_key}: all: - pip: - foobar @@ -3410,7 +3409,7 @@ def check(dirname): @pytest._change_default_pkg_key -def test_lock_file_has_invalid_packages(packages): +def test_lock_file_has_invalid_packages(pkg_key): def check(dirname): project = project_no_dedicated_env(dirname) @@ -3426,7 +3425,7 @@ def check(dirname): DEFAULT_PROJECT_LOCK_FILENAME: f""" env_specs: default: - {packages}: + {pkg_key}: all: - "=" - foo bar @@ -3436,7 +3435,7 @@ def check(dirname): }, check) -def test_lock_file_has_wrong_platforms(packages): +def test_lock_file_has_wrong_platforms(pkg_key): def check(dirname): project = project_no_dedicated_env(dirname) @@ -3453,13 +3452,13 @@ def check(dirname): env_specs: default: platforms: ["win-64"] - {packages}: + {pkg_key}: all: [foo] """ }, check) -def test_lock_file_has_zero_platforms(packages): +def test_lock_file_has_zero_platforms(pkg_key): def check(dirname): project = project_no_dedicated_env(dirname) @@ -3474,12 +3473,12 @@ def check(dirname): env_specs: default: platforms: [] - {packages}: + {pkg_key}: all: [foo] """}, check) -def test_lock_file_has_wrong_hash(packages): +def test_lock_file_has_wrong_hash(pkg_key): def check(dirname): project = project_no_dedicated_env(dirname) @@ -3497,25 +3496,25 @@ def check(dirname): default: env_spec_hash: wrong platforms: [linux-64,osx-64,win-64] - {packages}: + {pkg_key}: all: [foo] """ }, check) @pytest._change_default_pkg_key -def test_lock_file_has_empty_and_wrong_package_lists(packages): +def test_lock_file_has_empty_and_wrong_package_lists(pkg_key): def check(dirname): project = project_no_dedicated_env(dirname) assert [] == project.problems # yapf: disable assert [ - f'anaconda-project-lock.yml: Lock file lists no {packages} for env spec ' + f'anaconda-project-lock.yml: Lock file lists no {pkg_key} for env spec ' "'default' on platform linux-64", - f'anaconda-project-lock.yml: Lock file is missing 1 {packages} for env spec ' + f'anaconda-project-lock.yml: Lock file is missing 1 {pkg_key} for env spec ' 'default on osx-64 (hello)', - f'anaconda-project-lock.yml: Lock file lists no {packages} for env spec ' + f'anaconda-project-lock.yml: Lock file lists no {pkg_key} for env spec ' "'default' on platform win-64" ] == project.suggestions # yapf: enable @@ -3525,14 +3524,14 @@ def check(dirname): DEFAULT_PROJECT_FILENAME: f""" env_specs: default: - {packages}: + {pkg_key}: - hello """, DEFAULT_PROJECT_LOCK_FILENAME: f""" env_specs: default: platforms: [linux-64,osx-64,win-64] - {packages}: + {pkg_key}: linux-64: [] win-64: [] win-32: [foo] @@ -3542,7 +3541,7 @@ def check(dirname): }, check) -def test_lock_file_has_orphan_env_spec(packages): +def test_lock_file_has_orphan_env_spec(pkg_key): def check(dirname): project = project_no_dedicated_env(dirname) @@ -3555,23 +3554,23 @@ def check(dirname): DEFAULT_PROJECT_FILENAME: f""" env_specs: default: - {packages}: + {pkg_key}: - hello """, DEFAULT_PROJECT_LOCK_FILENAME: """ env_specs: default: platforms: [linux-64,osx-64,win-64] - packages: + : all: [hello] orphan: platforms: [linux-64,osx-64,win-64] - packages: {} -""".replace('packages', packages) + : {} +""".replace('', pkg_key) }, check) -def test_fix_project_file_with_no_platforms(packages): +def test_fix_project_file_with_no_platforms(pkg_key): def check(dirname): project = project_no_dedicated_env(dirname) @@ -3592,7 +3591,7 @@ def check(dirname): name: foo env_specs: default: - {packages}: + {pkg_key}: - hello """, DEFAULT_PROJECT_LOCK_FILENAME: """ @@ -3601,7 +3600,7 @@ def check(dirname): }, check) -def test_fix_env_spec_with_no_platforms(packages): +def test_fix_env_spec_with_no_platforms(pkg_key): def check(dirname): project = project_no_dedicated_env(dirname) @@ -3629,15 +3628,15 @@ def check(dirname): env_specs: default: platforms: ['linux-64'] - {packages}: + {pkg_key}: - hello foo: platforms: [] - {packages}: + {pkg_key}: - apackage bar: platforms: [] - {packages}: + {pkg_key}: - package2 """, DEFAULT_PROJECT_LOCK_FILENAME: """ diff --git a/anaconda_project/test/test_project_ops.py b/anaconda_project/test/test_project_ops.py index 47c695a5..c11ebc87 100644 --- a/anaconda_project/test/test_project_ops.py +++ b/anaconda_project/test/test_project_ops.py @@ -349,7 +349,7 @@ def check_add_var(dirname): with_directory_contents_completing_project_file({DEFAULT_PROJECT_FILENAME: ""}, check_add_var) -def test_add_variables_to_env_spec(packages): +def test_add_variables_to_env_spec(pkg_key): def check_add_var(dirname): project = project_no_dedicated_env(dirname) status = project_ops.add_variables(project, 'myspec', ['foo', 'baz'], dict(foo='bar')) @@ -366,10 +366,10 @@ def check_add_var(dirname): f""" env_specs: default: - {packages}: [python] + {pkg_key}: [python] channels: [] myspec: - {packages}: [python] + {pkg_key}: [python] channels: [] """ }, check_add_var) @@ -467,7 +467,7 @@ def check_remove_var(dirname): ' foo: baz\n bar: qux')}, check_remove_var) -def test_remove_variables_with_env_spec(packages): +def test_remove_variables_with_env_spec(pkg_key): def check_remove_var(dirname): project = project_no_dedicated_env(dirname) @@ -488,10 +488,10 @@ def check_remove_var(dirname): f""" env_specs: default: - {packages}: [python] + {pkg_key}: [python] channels: [] myspec: - {packages}: [python] + {pkg_key}: [python] channels: [] variables: foo: baz @@ -716,7 +716,7 @@ def check_add_command(dirname): with_directory_contents_completing_project_file({DEFAULT_PROJECT_FILENAME: ""}, check_add_command) -def test_add_command_bokeh_overwrites(packages): +def test_add_command_bokeh_overwrites(pkg_key): def check_add_command(dirname): project = project_no_dedicated_env(dirname) result = project_ops.add_command(project, 'bokeh_test', 'bokeh_app', 'file.py') @@ -733,12 +733,12 @@ def check_add_command(dirname): DEFAULT_PROJECT_FILENAME: ('commands:\n' ' bokeh_test:\n' ' bokeh_app: replaced.py\n' - f'{packages}:\n' + f'{pkg_key}:\n' ' - bokeh\n') }, check_add_command) -def test_add_command_sets_env_spec(packages): +def test_add_command_sets_env_spec(pkg_key): def check_add_command(dirname): project = project_no_dedicated_env(dirname) result = project_ops.add_command(project, 'bokeh_test', 'bokeh_app', 'file.py', env_spec_name='foo') @@ -752,14 +752,14 @@ def check_add_command(dirname): with_directory_contents_completing_project_file( { DEFAULT_PROJECT_FILENAME: ('env_specs:\n' - f' foo: {{ "{packages}" : ["bokeh"] }}\n' + f' foo: {{ "{pkg_key}" : ["bokeh"] }}\n' 'commands:\n' ' bokeh_test:\n' ' bokeh_app: replaced.py\n') }, check_add_command) -def test_add_command_leaves_env_spec(packages): +def test_add_command_leaves_env_spec(pkg_key): def check_add_command(dirname): project = project_no_dedicated_env(dirname) result = project_ops.add_command(project, 'bokeh_test', 'bokeh_app', 'file.py', env_spec_name=None) @@ -773,7 +773,7 @@ def check_add_command(dirname): with_directory_contents_completing_project_file( { DEFAULT_PROJECT_FILENAME: ('env_specs:\n' - f' foo: {{ "{packages}" : ["bokeh"] }}\n' + f' foo: {{ "{pkg_key}" : ["bokeh"] }}\n' 'commands:\n' ' bokeh_test:\n' ' env_spec: "foo"\n' @@ -782,7 +782,7 @@ def check_add_command(dirname): @pytest._change_default_pkg_key -def test_add_command_generates_env_spec_suggestion(packages): +def test_add_command_generates_env_spec_suggestion(pkg_key): def check_add_command(dirname): project = project_no_dedicated_env(dirname) assert project.problems == [] @@ -799,22 +799,22 @@ def check_add_command(dirname): command = re_loaded.get_value(['commands', 'bokeh_test']) assert command['bokeh_app'] == 'file.py' assert command['env_spec'] == 'bar' - assert re_loaded.get_value(['env_specs', 'bar', packages]) is None + assert re_loaded.get_value(['env_specs', 'bar', pkg_key]) is None assert project.problems == [] assert project.suggestions == [('%s: Command ' % project.project_file.basename) + - f'bokeh_test uses env spec bar which does not have the {packages}: bokeh'] + f'bokeh_test uses env spec bar which does not have the {pkg_key}: bokeh'] project.fix_problems_and_suggestions() project.project_file.save() re_loaded = ProjectFile.load_for_directory(project.directory_path) - assert re_loaded.get_value(['env_specs', 'bar', packages]) == ['bokeh'] + assert re_loaded.get_value(['env_specs', 'bar', pkg_key]) == ['bokeh'] with_directory_contents_completing_project_file( { DEFAULT_PROJECT_FILENAME: ('env_specs:\n' - f' foo: {{ "{packages}" : ["bokeh"] }}\n' + f' foo: {{ "{pkg_key}" : ["bokeh"] }}\n' ' bar: {}\n' 'commands:\n' ' bokeh_test:\n' @@ -823,7 +823,7 @@ def check_add_command(dirname): }, check_add_command) -def test_add_command_leaves_supports_http_options(packages): +def test_add_command_leaves_supports_http_options(pkg_key): def check_add_command(dirname): project = project_no_dedicated_env(dirname) result = project_ops.add_command(project, @@ -843,7 +843,7 @@ def check_add_command(dirname): with_directory_contents_completing_project_file( { DEFAULT_PROJECT_FILENAME: ('env_specs:\n' - f' foo: {{ "{packages}" : ["bokeh"] }}\n' + f' foo: {{ "{pkg_key}" : ["bokeh"] }}\n' 'commands:\n' ' bokeh_test:\n' ' supports_http_options: false\n' @@ -851,7 +851,7 @@ def check_add_command(dirname): }, check_add_command) -def test_add_command_leaves_supports_http_options_unset(packages): +def test_add_command_leaves_supports_http_options_unset(pkg_key): def check_add_command(dirname): project = project_no_dedicated_env(dirname) result = project_ops.add_command(project, @@ -871,14 +871,14 @@ def check_add_command(dirname): with_directory_contents_completing_project_file( { DEFAULT_PROJECT_FILENAME: ('env_specs:\n' - f' foo: {{ "{packages}" : ["bokeh"] }}\n' + f' foo: {{ "{pkg_key}" : ["bokeh"] }}\n' 'commands:\n' ' bokeh_test:\n' ' bokeh_app: replaced.py\n') }, check_add_command) -def test_add_command_modifies_supports_http_options(packages): +def test_add_command_modifies_supports_http_options(pkg_key): def check_add_command(dirname): project = project_no_dedicated_env(dirname) result = project_ops.add_command(project, @@ -898,7 +898,7 @@ def check_add_command(dirname): with_directory_contents_completing_project_file( { DEFAULT_PROJECT_FILENAME: ('env_specs:\n' - f' foo: {{ "{packages}" : ["bokeh"] }}\n' + f' foo: {{ "{pkg_key}" : ["bokeh"] }}\n' 'commands:\n' ' bokeh_test:\n' ' supports_http_options: false\n' @@ -1253,7 +1253,7 @@ def check(dirname): with_directory_contents_completing_project_file(dict(), check) -def test_add_download_to_env_spec(monkeypatch, packages): +def test_add_download_to_env_spec(monkeypatch, pkg_key): def check(dirname): _monkeypatch_download_file(monkeypatch, dirname) @@ -1276,10 +1276,10 @@ def check(dirname): r""" env_specs: default: - {packages}: [python] + {pkg_key}: [python] channels: [] myspec: - {packages}: [python] + {pkg_key}: [python] channels: [] """ }, check) @@ -1490,7 +1490,7 @@ def check(dirname): """}, check) -def test_remove_download_with_env_spec(monkeypatch, packages): +def test_remove_download_with_env_spec(monkeypatch, pkg_key): def check(dirname): config_path = ['env_specs', 'myspec', 'downloads', 'MYDATA'] project = project_no_dedicated_env(dirname) @@ -1510,10 +1510,10 @@ def check(dirname): f""" env_specs: default: - {packages}: [python] + {pkg_key}: [python] channels: [] myspec: - {packages}: [python] + {pkg_key}: [python] channels: [] downloads: MYDATA: "http://localhost:123456" @@ -1529,7 +1529,7 @@ def check(dirname): # then we add a latest version of pandas. If anaconda-project does the right thing, # conda will install an earlier version of pandas to respect the numpy version pin. @pytest.mark.slow -def test_add_env_spec_with_real_conda_manager(monkeypatch): +def test_add_env_spec_with_real_conda_manager(monkeypatch, pkg_key): monkeypatch_conda_not_to_use_links(monkeypatch) _monkeypatch_reduced_environment(monkeypatch) @@ -1539,9 +1539,9 @@ def check(dirname): pip_spec = ['chardet'] for spec in specs: if spec == specs[0]: - status = project_ops.add_env_spec(project, name='foo', packages=[spec], channels=[]) + status = project_ops.add_env_spec(project, name='foo', pkg_key=[spec], channels=[]) else: - status = project_ops.add_packages(project, 'foo', packages=[spec], channels=[]) + status = project_ops.add_packages(project, 'foo', pkg_key=[spec], channels=[]) if not status: print(status.status_description) print(repr(status.errors)) @@ -1555,7 +1555,7 @@ def check(dirname): # be sure it was really done project2 = Project(dirname) env_commented_map = project2.project_file.get_value(['env_specs', 'foo']) - assert spec in env_commented_map['packages'], env_commented_map['packages'] + assert spec in env_commented_map[pkg_key], env_commented_map[pkg_key] # ensure numpy <1.11.3 is present in both passes meta_path = os.path.join(dirname, 'envs', 'foo', 'conda-meta') @@ -1635,7 +1635,8 @@ def _with_conda_test(f, _pop_conda_test() -def test_add_env_spec(): +@pytest._change_default_pkg_key +def test_add_env_spec(pkg_key): def check(dirname): def attempt(): project = Project(dirname) @@ -1649,23 +1650,24 @@ def attempt(): # be sure we really made the config changes project2 = Project(dirname) - assert dict(packages=[], channels=[]) == dict(project2.project_file.get_value(['env_specs', 'foo'])) - assert dict(packages=[], channels=[]) == dict(project2.project_file.get_value(['env_specs', 'bar'])) - assert dict(locked=True, + assert dict({pkg_key: []}, channels=[]) == dict(project2.project_file.get_value(['env_specs', 'foo'])) + assert dict({pkg_key: []}, channels=[]) == dict(project2.project_file.get_value(['env_specs', 'bar'])) + assert dict({pkg_key: dict(all=[])}, + locked=True, env_spec_hash='a30f02c961ef4f3fe07ceb09e0906394c3885a79', - packages=dict(all=[]), platforms=['linux-64', 'osx-64', 'win-64']) == dict(project2.lock_file.get_value(['env_specs', 'foo'])) - assert dict(locked=True, + assert dict({pkg_key: dict(all=[])}, + locked=True, env_spec_hash='a30f02c961ef4f3fe07ceb09e0906394c3885a79', - packages=dict(all=[]), platforms=['linux-64', 'osx-64', 'win-64']) == dict(project2.lock_file.get_value(['env_specs', 'bar'])) with_directory_contents_completing_project_file({DEFAULT_PROJECT_LOCK_FILENAME: "locking_enabled: true\n"}, check) -def test_add_env_spec_no_global_platforms(): +@pytest._change_default_pkg_key +def test_add_env_spec_no_global_platforms(pkg_key): def check(dirname): def attempt(): project = Project(dirname) @@ -1686,20 +1688,21 @@ def attempt(): # be sure we really made the config changes project2 = Project(dirname) - assert dict(packages=[], channels=[], + assert dict({pkg_key: []}, channels=[], platforms=['linux-64', 'osx-64', 'win-64']) == dict(project2.project_file.get_value(['env_specs', 'foo'])) - assert dict(locked=True, + assert dict({pkg_key: dict(all=[])}, + locked=True, env_spec_hash='a30f02c961ef4f3fe07ceb09e0906394c3885a79', - packages=dict(all=[]), platforms=['linux-64', 'osx-64', 'win-64']) == dict(project2.lock_file.get_value(['env_specs', 'foo'])) with_directory_contents_completing_project_file({DEFAULT_PROJECT_LOCK_FILENAME: "locking_enabled: true\n"}, check) -def test_add_env_spec_with_packages_and_channels(): +@pytest._change_default_pkg_key +def test_add_env_spec_with_packages_and_channels(pkg_key): def check(dirname): def attempt(): project = Project(dirname) @@ -1713,7 +1716,7 @@ def attempt(): # be sure download was added to the file and saved project2 = Project(dirname) - assert dict(packages=['a', 'b', 'c'], + assert dict({pkg_key: ['a', 'b', 'c']}, channels=['c1', 'c2', 'c3']) == dict(project2.project_file.get_value(['env_specs', 'foo'])) env_spec = project2.env_specs['foo'] @@ -1725,7 +1728,7 @@ def attempt(): @pytest._change_default_pkg_key -def test_add_env_spec_extending_existing_lists(packages): +def test_add_env_spec_extending_existing_lists(pkg_key): def check(dirname): def attempt(): project = Project(dirname) @@ -1739,20 +1742,20 @@ def attempt(): # be sure download was added to the file and saved project2 = Project(dirname) - assert dict({packages: ['b', 'a', 'c']}, + assert dict({pkg_key: ['b', 'a', 'c']}, channels=['c3', 'c1', 'c2']) == dict(project2.project_file.get_value(['env_specs', 'foo'])) with_directory_contents_completing_project_file( {DEFAULT_PROJECT_FILENAME: f""" env_specs: foo: - {packages}: [ 'b' ] + {pkg_key}: [ 'b' ] channels: [ 'c3'] """}, check) @pytest._change_default_pkg_key -def test_add_env_spec_extending_existing_lists_with_versions(packages): +def test_add_env_spec_extending_existing_lists_with_versions(pkg_key): def check(dirname): def attempt(): project = Project(dirname) @@ -1766,14 +1769,14 @@ def attempt(): # be sure download was added to the file and saved project2 = Project(dirname) - assert dict({packages: ['b=2.0', 'a', 'c']}, + assert dict({pkg_key: ['b=2.0', 'a', 'c']}, channels=['c3', 'c1', 'c2']) == dict(project2.project_file.get_value(['env_specs', 'foo'])) with_directory_contents_completing_project_file( {DEFAULT_PROJECT_FILENAME: f""" env_specs: foo: - {packages}: [ 'b=1.0' ] + {pkg_key}: [ 'b=1.0' ] channels: [ 'c3'] """}, check) @@ -1799,7 +1802,7 @@ def attempt(): @pytest._change_default_pkg_key -def test_remove_env_spec(packages): +def test_remove_env_spec(pkg_key): def check(dirname): def attempt(): project = Project(dirname) @@ -1828,10 +1831,10 @@ def attempt(): name: foo env_specs: hello: - {packages}: + {pkg_key}: - a another: - {packages}: + {pkg_key}: - b """, DEFAULT_PROJECT_LOCK_FILENAME: f""" @@ -1839,14 +1842,14 @@ def attempt(): env_specs: hello: platforms: [linux-32,linux-64,osx-64,win-32,win-64] - {packages}: + {pkg_key}: all: - a=1.0=1 """ }, check) -def test_remove_only_env_spec(packages): +def test_remove_only_env_spec(pkg_key): def check(dirname): def attempt(): project = Project(dirname) @@ -1871,13 +1874,13 @@ def attempt(): name: foo env_specs: hello: - {packages}: + {pkg_key}: - a """}, check) @pytest._change_default_pkg_key -def test_remove_env_spec_causes_problem(packages): +def test_remove_env_spec_causes_problem(pkg_key): def check(dirname): def attempt(): project = Project(dirname) @@ -1912,10 +1915,10 @@ def attempt(): env_spec: hello env_specs: hello: - {packages}: + {pkg_key}: - a another: - {packages}: + {pkg_key}: - b """, DEFAULT_PROJECT_LOCK_FILENAME: f""" @@ -1923,14 +1926,14 @@ def attempt(): env_specs: hello: platforms: [linux-32,linux-64,osx-64,win-32,win-64] - {packages}: + {pkg_key}: all: - a=1.0=1 """ }, check) -def test_add_packages_to_all_environments(packages): +def test_add_packages_to_all_environments(pkg_key): def check(dirname): def attempt(): project = Project(dirname) @@ -1945,7 +1948,7 @@ def attempt(): # be sure we really made the config changes project2 = Project(dirname) - assert [dict(pip=[]), 'foo', 'bar'] == list(project2.project_file.get_value(packages)) + assert [dict(pip=[]), 'foo', 'bar'] == list(project2.project_file.get_value(pkg_key)) assert ['hello', 'world'] == list(project2.project_file.get_value('channels')) for env_spec in project2.env_specs.values(): @@ -1956,14 +1959,14 @@ def attempt(): with_directory_contents_completing_project_file( { DEFAULT_PROJECT_FILENAME: f""" -{packages}: +{pkg_key}: - pip: [] # be sure we don't break with this in the list """, DEFAULT_PROJECT_LOCK_FILENAME: "locking_enabled: true\n" }, check) -def test_add_pip_packages_to_all_environments(packages): +def test_add_pip_packages_to_all_environments(pkg_key): def check(dirname): def attempt(): project = Project(dirname) @@ -1981,7 +1984,7 @@ def attempt(): project2 = Project(dirname) assert [ dict(pip=['foo', 'bar']), - ] == list(project2.project_file.get_value(packages)) + ] == list(project2.project_file.get_value(pkg_key)) # assert ['hello', 'world'] == list(project2.project_file.get_value('channels')) for env_spec in project2.env_specs.values(): @@ -1992,14 +1995,14 @@ def attempt(): with_directory_contents_completing_project_file( { DEFAULT_PROJECT_FILENAME: f""" -{packages}: +{pkg_key}: - pip: [] # be sure we don't break with this in the list """, DEFAULT_PROJECT_LOCK_FILENAME: "locking_enabled: true\n" }, check) -def test_add_packages_cannot_resolve_deps(): +def test_add_packages_cannot_resolve_deps(pkg_key): def check(dirname): def attempt(): project = Project(dirname, frontend=FakeFrontend()) @@ -2016,7 +2019,7 @@ def attempt(): # be sure we didn't make the config changes project2 = Project(dirname) - assert project2.project_file.get_value('packages', None) is None + assert project2.project_file.get_value(pkg_key, None) is None assert project2.project_file.get_value('channels', None) is None for env_spec in project2.env_specs.values(): @@ -2056,7 +2059,7 @@ def attempt(): with_directory_contents_completing_project_file(dict(), check) -def test_remove_packages_from_all_environments(packages): +def test_remove_packages_from_all_environments(pkg_key): def check(dirname): def attempt(): os.makedirs(os.path.join(dirname, 'envs', 'hello')) # forces us to really run remove_packages @@ -2065,8 +2068,8 @@ def attempt(): assert env_spec.lock_set.enabled assert env_spec.lock_set.platforms == () - assert ['foo', 'bar', 'baz'] == list(project.project_file.get_value(packages)) - assert ['foo', 'woot'] == list(project.project_file.get_value(['env_specs', 'hello', packages], [])) + assert ['foo', 'bar', 'baz'] == list(project.project_file.get_value(pkg_key)) + assert ['foo', 'woot'] == list(project.project_file.get_value(['env_specs', 'hello', pkg_key], [])) status = project_ops.remove_packages(project, env_spec_name=None, packages=['foo', 'bar']) assert [] == status.errors assert status @@ -2075,8 +2078,8 @@ def attempt(): # be sure we really made the config changes project2 = Project(dirname) - assert ['baz'] == list(project2.project_file.get_value(packages)) - assert ['woot'] == list(project2.project_file.get_value(['env_specs', 'hello', packages])) + assert ['baz'] == list(project2.project_file.get_value(pkg_key)) + assert ['woot'] == list(project2.project_file.get_value(['env_specs', 'hello', pkg_key])) for env_spec in project2.env_specs.values(): assert env_spec.lock_set.enabled @@ -2086,17 +2089,17 @@ def attempt(): with_directory_contents_completing_project_file( { DEFAULT_PROJECT_FILENAME: f""" -{packages}: +{pkg_key}: - foo - bar - baz env_specs: hello: - {packages}: + {pkg_key}: - foo - woot hello2: - {packages}: + {pkg_key}: - foo - bar - pip: [] # make sure we don't choke on non-string items in list @@ -2105,7 +2108,7 @@ def attempt(): }, check) -def test_remove_conda_packages_from_global_with_pip_packages(packages): +def test_remove_conda_packages_from_global_with_pip_packages(pkg_key): def check(dirname): def attempt(): os.makedirs(os.path.join(dirname, 'envs', 'hello')) # forces us to really run remove_packages @@ -2114,8 +2117,8 @@ def attempt(): assert env_spec.lock_set.enabled assert env_spec.lock_set.platforms == () - assert ['foo', 'bar', 'baz', OrderedDict([('pip', [])])] == list(project.project_file.get_value(packages)) - assert ['foo', 'woot'] == list(project.project_file.get_value(['env_specs', 'hello', packages], [])) + assert ['foo', 'bar', 'baz', OrderedDict([('pip', [])])] == list(project.project_file.get_value(pkg_key)) + assert ['foo', 'woot'] == list(project.project_file.get_value(['env_specs', 'hello', pkg_key], [])) status = project_ops.remove_packages(project, env_spec_name=None, packages=['foo', 'bar']) assert [] == status.errors assert status @@ -2124,8 +2127,8 @@ def attempt(): # be sure we really made the config changes project2 = Project(dirname) - assert ['baz', OrderedDict([('pip', [])])] == list(project2.project_file.get_value(packages)) - assert ['woot'] == list(project2.project_file.get_value(['env_specs', 'hello', packages])) + assert ['baz', OrderedDict([('pip', [])])] == list(project2.project_file.get_value(pkg_key)) + assert ['woot'] == list(project2.project_file.get_value(['env_specs', 'hello', pkg_key])) for env_spec in project2.env_specs.values(): assert env_spec.lock_set.enabled @@ -2135,18 +2138,18 @@ def attempt(): with_directory_contents_completing_project_file( { DEFAULT_PROJECT_FILENAME: f""" -{packages}: +{pkg_key}: - foo - bar - baz - pip: [] env_specs: hello: - {packages}: + {pkg_key}: - foo - woot hello2: - {packages}: + {pkg_key}: - foo - bar - pip: [] # make sure we don't choke on non-string items in list @@ -2155,7 +2158,7 @@ def attempt(): }, check) -def test_remove_pip_packages_from_global(packages): +def test_remove_pip_packages_from_global(pkg_key): def check(dirname): def attempt(): os.makedirs(os.path.join(dirname, 'envs', 'hello')) # forces us to really run remove_packages @@ -2164,9 +2167,9 @@ def attempt(): assert env_spec.lock_set.enabled assert env_spec.lock_set.platforms == () - assert ['foo', OrderedDict([('pip', ['bar', 'baz'])])] == list(project.project_file.get_value(packages)) + assert ['foo', OrderedDict([('pip', ['bar', 'baz'])])] == list(project.project_file.get_value(pkg_key)) assert ['foo', OrderedDict([('pip', ['bar', 'woot'])]) - ] == list(project.project_file.get_value(['env_specs', 'hello', packages], [])) + ] == list(project.project_file.get_value(['env_specs', 'hello', pkg_key], [])) status = project_ops.remove_packages(project, env_spec_name=None, packages=['bar'], pip=True) assert [] == status.errors assert status @@ -2175,9 +2178,9 @@ def attempt(): # be sure we really made the config changes project2 = Project(dirname) - assert ['foo', OrderedDict([('pip', ['baz'])])] == list(project2.project_file.get_value(packages)) + assert ['foo', OrderedDict([('pip', ['baz'])])] == list(project2.project_file.get_value(pkg_key)) assert ['foo', OrderedDict([('pip', ['woot'])]) - ] == list(project2.project_file.get_value(['env_specs', 'hello', packages])) + ] == list(project2.project_file.get_value(['env_specs', 'hello', pkg_key])) for env_spec in project2.env_specs.values(): assert env_spec.lock_set.enabled @@ -2187,14 +2190,14 @@ def attempt(): with_directory_contents_completing_project_file( { DEFAULT_PROJECT_FILENAME: f""" -{packages}: +{pkg_key}: - foo - pip: - bar - baz env_specs: hello: - {packages}: + {pkg_key}: - foo - pip: - bar @@ -2205,7 +2208,7 @@ def attempt(): }, check) -def test_remove_pip_packages_from_one_environment(packages): +def test_remove_pip_packages_from_one_environment(pkg_key): def check(dirname): def attempt(): project = Project(dirname) @@ -2215,7 +2218,7 @@ def attempt(): assert env_spec.lock_set.platforms == () assert ['qbert', OrderedDict([('pip', ['pbert', 'foo', - 'bar'])])] == list(project.project_file.get_value(packages)) + 'bar'])])] == list(project.project_file.get_value(pkg_key)) status = project_ops.remove_packages(project, env_spec_name='hello', packages=['foo', 'bar'], pip=True) assert status assert [] == status.errors @@ -2226,9 +2229,9 @@ def attempt(): project2 = Project(dirname) # note that hello will still inherit the deps from the global packages, # and that's fine - assert ['qbert', OrderedDict([('pip', ['pbert'])])] == list(project2.project_file.get_value(packages)) + assert ['qbert', OrderedDict([('pip', ['pbert'])])] == list(project2.project_file.get_value(pkg_key)) assert [OrderedDict([('pip', [])]) - ] == list(project2.project_file.get_value(['env_specs', 'hello', packages], [])) + ] == list(project2.project_file.get_value(['env_specs', 'hello', pkg_key], [])) # be sure we didn't delete comments from global packages section content = codecs.open(project2.project_file.filename, 'r', 'utf-8').read() @@ -2246,7 +2249,7 @@ def attempt(): with_directory_contents_completing_project_file( { DEFAULT_PROJECT_FILENAME: f""" -{packages}: +{pkg_key}: # this is a pre comment - qbert # this is a post comment - pip: @@ -2255,7 +2258,7 @@ def attempt(): - bar env_specs: hello: - {packages}: + {pkg_key}: - pip: - foo """, @@ -2263,7 +2266,7 @@ def attempt(): }, check) -def test_remove_pip_packages_from_one_environment_with_pkgs(packages): +def test_remove_pip_packages_from_one_environment_with_pkgs(pkg_key): def check(dirname): def attempt(): project = Project(dirname) @@ -2273,7 +2276,7 @@ def attempt(): assert env_spec.lock_set.platforms == () assert ['qbert', OrderedDict([('pip', ['pbert', 'foo', - 'bar'])])] == list(project.project_file.get_value(packages)) + 'bar'])])] == list(project.project_file.get_value(pkg_key)) status = project_ops.remove_packages(project, env_spec_name='hello', packages=['foo', 'bar'], pip=True) assert status assert [] == status.errors @@ -2284,9 +2287,9 @@ def attempt(): project2 = Project(dirname) # note that hello will still inherit the deps from the global packages, # and that's fine - assert ['qbert', OrderedDict([('pip', ['pbert'])])] == list(project2.project_file.get_value(packages)) + assert ['qbert', OrderedDict([('pip', ['pbert'])])] == list(project2.project_file.get_value(pkg_key)) assert ['qbert', OrderedDict([('pip', [])]) - ] == list(project2.project_file.get_value(['env_specs', 'hello', packages], [])) + ] == list(project2.project_file.get_value(['env_specs', 'hello', pkg_key], [])) # be sure we didn't delete comments from global packages section content = codecs.open(project2.project_file.filename, 'r', 'utf-8').read() @@ -2304,7 +2307,7 @@ def attempt(): with_directory_contents_completing_project_file( { DEFAULT_PROJECT_FILENAME: f""" -{packages}: +{pkg_key}: # this is a pre comment - qbert # this is a post comment - pip: @@ -2313,14 +2316,14 @@ def attempt(): - bar env_specs: hello: - {packages}: + {pkg_key}: - qbert """, DEFAULT_PROJECT_LOCK_FILENAME: "locking_enabled: true\n" }, check) -def test_remove_pip_packages_from_one_environment_empty_pkgs(packages): +def test_remove_pip_packages_from_one_environment_empty_pkgs(pkg_key): def check(dirname): def attempt(): project = Project(dirname) @@ -2330,7 +2333,7 @@ def attempt(): assert env_spec.lock_set.platforms == () assert ['qbert', OrderedDict([('pip', ['pbert', 'foo', - 'bar'])])] == list(project.project_file.get_value(packages)) + 'bar'])])] == list(project.project_file.get_value(pkg_key)) status = project_ops.remove_packages(project, env_spec_name='hello', packages=['foo', 'bar'], pip=True) assert status assert [] == status.errors @@ -2341,9 +2344,9 @@ def attempt(): project2 = Project(dirname) # note that hello will still inherit the deps from the global packages, # and that's fine - assert ['qbert', OrderedDict([('pip', ['pbert'])])] == list(project2.project_file.get_value(packages)) + assert ['qbert', OrderedDict([('pip', ['pbert'])])] == list(project2.project_file.get_value(pkg_key)) assert [OrderedDict([('pip', [])]) - ] == list(project2.project_file.get_value(['env_specs', 'hello', packages], [])) + ] == list(project2.project_file.get_value(['env_specs', 'hello', pkg_key], [])) # be sure we didn't delete comments from global packages section content = codecs.open(project2.project_file.filename, 'r', 'utf-8').read() @@ -2361,7 +2364,7 @@ def attempt(): with_directory_contents_completing_project_file( { DEFAULT_PROJECT_FILENAME: f""" -{packages}: +{pkg_key}: # this is a pre comment - qbert # this is a post comment - pip: @@ -2370,13 +2373,13 @@ def attempt(): - bar env_specs: hello: - {packages}: [] + {pkg_key}: [] """, DEFAULT_PROJECT_LOCK_FILENAME: "locking_enabled: true\n" }, check) -def test_remove_packages_from_one_environment(packages): +def test_remove_packages_from_one_environment(pkg_key): def check(dirname): def attempt(): project = Project(dirname) @@ -2385,8 +2388,8 @@ def attempt(): assert env_spec.lock_set.enabled assert env_spec.lock_set.platforms == () - assert ['qbert', 'foo', 'bar'] == list(project.project_file.get_value(packages)) - assert ['foo'] == list(project.project_file.get_value(['env_specs', 'hello', packages], [])) + assert ['qbert', 'foo', 'bar'] == list(project.project_file.get_value(pkg_key)) + assert ['foo'] == list(project.project_file.get_value(['env_specs', 'hello', pkg_key], [])) status = project_ops.remove_packages(project, env_spec_name='hello', packages=['foo', 'bar']) assert status assert [] == status.errors @@ -2397,8 +2400,8 @@ def attempt(): project2 = Project(dirname) # note that hello will still inherit the deps from the global packages, # and that's fine - assert ['qbert'] == list(project2.project_file.get_value(packages)) - assert [] == list(project2.project_file.get_value(['env_specs', 'hello', packages], [])) + assert ['qbert'] == list(project2.project_file.get_value(pkg_key)) + assert [] == list(project2.project_file.get_value(['env_specs', 'hello', pkg_key], [])) # be sure we didn't delete comments from global packages section content = codecs.open(project2.project_file.filename, 'r', 'utf-8').read() @@ -2416,26 +2419,26 @@ def attempt(): with_directory_contents_completing_project_file( { DEFAULT_PROJECT_FILENAME: f""" -{packages}: +{pkg_key}: # this is a pre comment - qbert # this is a post comment - foo - bar env_specs: hello: - {packages}: + {pkg_key}: - foo """, DEFAULT_PROJECT_LOCK_FILENAME: "locking_enabled: true\n" }, check) -def test_remove_packages_from_one_environment_leaving_others_unaffected(packages): +def test_remove_packages_from_one_environment_leaving_others_unaffected(pkg_key): def check(dirname): def attempt(): project = Project(dirname) - assert ['qbert', 'foo', 'bar'] == list(project.project_file.get_value(packages)) - assert ['foo'] == list(project.project_file.get_value(['env_specs', 'hello', packages], [])) + assert ['qbert', 'foo', 'bar'] == list(project.project_file.get_value(pkg_key)) + assert ['foo'] == list(project.project_file.get_value(['env_specs', 'hello', pkg_key], [])) status = project_ops.remove_packages(project, env_spec_name='hello', packages=['foo', 'bar']) assert status assert [] == status.errors @@ -2444,10 +2447,10 @@ def attempt(): # be sure we really made the config changes project2 = Project(dirname) - assert ['qbert'] == list(project2.project_file.get_value(packages)) - assert [] == list(project2.project_file.get_value(['env_specs', 'hello', packages], [])) + assert ['qbert'] == list(project2.project_file.get_value(pkg_key)) + assert [] == list(project2.project_file.get_value(['env_specs', 'hello', pkg_key], [])) assert set(['baz', 'foo', - 'bar']) == set(project2.project_file.get_value(['env_specs', 'another', packages], [])) + 'bar']) == set(project2.project_file.get_value(['env_specs', 'another', pkg_key], [])) assert project2.env_specs['another'].conda_package_names_set == set(['qbert', 'foo', 'bar', 'baz']) assert project2.env_specs['hello'].conda_package_names_set == set(['qbert']) @@ -2459,28 +2462,28 @@ def attempt(): with_directory_contents_completing_project_file( { DEFAULT_PROJECT_FILENAME: f""" -{packages}: +{pkg_key}: - qbert - foo - bar env_specs: hello: - {packages}: + {pkg_key}: - foo another: - {packages}: + {pkg_key}: # this is a pre comment - baz # this is a post comment """ }, check) -def test_remove_pip_packages_from_one_environment_leaving_others_unaffected(packages): +def test_remove_pip_packages_from_one_environment_leaving_others_unaffected(pkg_key): def check(dirname): def attempt(): project = Project(dirname) assert ['qbert', OrderedDict([('pip', ['pbert', 'foo', - 'bar'])])] == list(project.project_file.get_value(packages)) + 'bar'])])] == list(project.project_file.get_value(pkg_key)) status = project_ops.remove_packages(project, env_spec_name='hello', packages=['foo', 'bar'], pip=True) assert status assert [] == status.errors @@ -2489,11 +2492,11 @@ def attempt(): # be sure we really made the config changes project2 = Project(dirname) - assert ['qbert', OrderedDict([('pip', ['pbert'])])] == list(project2.project_file.get_value(packages)) + assert ['qbert', OrderedDict([('pip', ['pbert'])])] == list(project2.project_file.get_value(pkg_key)) assert [OrderedDict([('pip', [])]) - ] == list(project2.project_file.get_value(['env_specs', 'hello', packages], [])) + ] == list(project2.project_file.get_value(['env_specs', 'hello', pkg_key], [])) assert set(['baz', 'foo', - 'bar']) == set(project2.project_file.get_value(['env_specs', 'another', packages], [])[0]['pip']) + 'bar']) == set(project2.project_file.get_value(['env_specs', 'another', pkg_key], [])[0]['pip']) assert project2.env_specs['another'].pip_package_names_set == set(['foo', 'bar', 'baz', 'pbert']) assert project2.env_specs['hello'].pip_package_names_set == set(['pbert']) @@ -2505,7 +2508,7 @@ def attempt(): with_directory_contents_completing_project_file( { DEFAULT_PROJECT_FILENAME: f""" -{packages}: +{pkg_key}: - qbert - pip: - pbert @@ -2513,11 +2516,11 @@ def attempt(): - bar env_specs: hello: - {packages}: + {pkg_key}: - pip: - foo another: - {packages}: + {pkg_key}: - pip: # this is a pre comment - baz # this is a post comment @@ -2525,7 +2528,7 @@ def attempt(): }, check) -def test_remove_packages_cannot_resolve_deps(packages): +def test_remove_packages_cannot_resolve_deps(pkg_key): def check(dirname): def attempt(): os.makedirs(os.path.join(dirname, 'envs', 'hello')) # forces us to really run remove_packages @@ -2534,8 +2537,8 @@ def attempt(): assert env_spec.lock_set.enabled assert env_spec.lock_set.platforms == () - assert ['foo', 'bar', 'baz'] == list(project.project_file.get_value(packages)) - assert ['foo', 'woot'] == list(project.project_file.get_value(['env_specs', 'hello', packages], [])) + assert ['foo', 'bar', 'baz'] == list(project.project_file.get_value(pkg_key)) + assert ['foo', 'woot'] == list(project.project_file.get_value(['env_specs', 'hello', pkg_key], [])) status = project_ops.remove_packages(project, env_spec_name=None, packages=['foo', 'bar']) assert status.status_description == "Error resolving dependencies for hello: NOPE." assert status.errors == [] @@ -2546,8 +2549,8 @@ def attempt(): # be sure we didn't make the config changes project2 = Project(dirname) - assert ['foo', 'bar', 'baz'] == list(project2.project_file.get_value(packages)) - assert ['foo', 'woot'] == list(project2.project_file.get_value(['env_specs', 'hello', packages])) + assert ['foo', 'bar', 'baz'] == list(project2.project_file.get_value(pkg_key)) + assert ['foo', 'woot'] == list(project2.project_file.get_value(['env_specs', 'hello', pkg_key])) for env_spec in project2.env_specs.values(): assert env_spec.lock_set.enabled @@ -2556,13 +2559,13 @@ def attempt(): with_directory_contents_completing_project_file( { DEFAULT_PROJECT_FILENAME: f""" -{packages}: +{pkg_key}: - foo - bar - baz env_specs: hello: - {packages}: + {pkg_key}: - foo - woot """, @@ -2570,11 +2573,11 @@ def attempt(): }, check) -def test_remove_packages_from_nonexistent_environment(packages): +def test_remove_packages_from_nonexistent_environment(pkg_key): def check(dirname): def attempt(): project = Project(dirname) - assert ['foo', 'bar'] == list(project.project_file.get_value(packages)) + assert ['foo', 'bar'] == list(project.project_file.get_value(pkg_key)) status = project_ops.remove_packages(project, env_spec_name='not_an_environment', packages=['foo', 'bar']) assert not status assert [] == status.errors @@ -2584,10 +2587,10 @@ def attempt(): # be sure we didn't make the config changes project2 = Project(dirname) - assert ['foo', 'bar'] == list(project2.project_file.get_value(packages)) + assert ['foo', 'bar'] == list(project2.project_file.get_value(pkg_key)) with_directory_contents_completing_project_file({DEFAULT_PROJECT_FILENAME: f""" -{packages}: +{pkg_key}: - foo - bar """}, check) @@ -2924,7 +2927,7 @@ def attempt(): @pytest._change_default_pkg_key -def test_lock_and_update_and_unlock_all_envs(packages): +def test_lock_and_update_and_unlock_all_envs(pkg_key): def check(dirname): resolve_results = {'all': ['a=1.0=1'], 'pip': ['cc==1.0']} @@ -2950,7 +2953,7 @@ def attempt(): '+ linux-64', '+ osx-64', '+ win-64', - f' {packages}:', + f' {pkg_key}:', '+ all:', '+ a=1.0=1', '+ pip:', @@ -2962,7 +2965,7 @@ def attempt(): '+ linux-64', '+ osx-64', '+ win-64', - f' {packages}:', + f' {pkg_key}:', '+ all:', '+ a=1.0=1', '+ pip:', @@ -3049,12 +3052,12 @@ def attempt(): name: locktest env_specs: foo: - {packages}: + {pkg_key}: - a - pip: - cc bar: - {packages}: + {pkg_key}: - b - pip: - dd @@ -3063,7 +3066,7 @@ def attempt(): @pytest._change_default_pkg_key -def test_lock_and_unlock_single_env(packages): +def test_lock_and_unlock_single_env(pkg_key): def check(dirname): def attempt(): filename = os.path.join(dirname, DEFAULT_PROJECT_LOCK_FILENAME) @@ -3087,7 +3090,7 @@ def attempt(): '+ linux-64', '+ osx-64', '+ win-64', - f' {packages}:', + f' {pkg_key}:', '+ all:', '+ a=1.0=1', 'Added locked dependencies for env spec foo to anaconda-project-lock.yml.'] == project.frontend.logs @@ -3169,18 +3172,18 @@ def attempt(): name: locktest env_specs: foo: - {packages}: + {pkg_key}: - a bar: platforms: [osx-64] - {packages}: + {pkg_key}: - b """ }, check) @pytest._change_default_pkg_key -def test_locking_with_missing_lock_set_does_an_update(packages): +def test_locking_with_missing_lock_set_does_an_update(pkg_key): def check(dirname): def attempt(): filename = os.path.join(dirname, DEFAULT_PROJECT_LOCK_FILENAME) @@ -3205,7 +3208,7 @@ def attempt(): '+ linux-64', '+ osx-64', '+ win-64', - f' {packages}:', + f' {pkg_key}:', '+ all:', '+ a=1.0=1', 'Added locked dependencies for env spec foo to anaconda-project-lock.yml.'] == project.frontend.logs @@ -3231,7 +3234,7 @@ def attempt(): platforms: [linux-64,osx-64,win-64] env_specs: foo: - {packages}: + {pkg_key}: - a """, DEFAULT_PROJECT_LOCK_FILENAME: """ @@ -3242,7 +3245,7 @@ def attempt(): @pytest._change_default_pkg_key -def test_update_changes_only_the_hash(packages): +def test_update_changes_only_the_hash(pkg_key): def check(dirname): def attempt(): project = Project(dirname, frontend=FakeFrontend()) @@ -3277,7 +3280,7 @@ def attempt(): platforms: [linux-32,linux-64,osx-64,win-32,win-64] env_specs: foo: - {packages}: + {pkg_key}: - a """, DEFAULT_PROJECT_LOCK_FILENAME: f""" @@ -3286,13 +3289,13 @@ def attempt(): foo: platforms: [linux-32,linux-64,osx-64,win-32,win-64] env_spec_hash: old - {packages}: + {pkg_key}: all: ['a=1.0=1'] """ }, check) -def test_lock_conda_error(packages): +def test_lock_conda_error(pkg_key): def check(dirname): def attempt(): filename = os.path.join(dirname, DEFAULT_PROJECT_LOCK_FILENAME) @@ -3318,16 +3321,16 @@ def attempt(): platforms: [linux-32,linux-64,osx-64,win-32,win-64] env_specs: foo: - {packages}: + {pkg_key}: - a bar: - {packages}: + {pkg_key}: - b """ }, check) -def test_lock_resolve_dependencies_error(monkeypatch, packages): +def test_lock_resolve_dependencies_error(monkeypatch, pkg_key): def check(dirname): def attempt(): filename = os.path.join(dirname, DEFAULT_PROJECT_LOCK_FILENAME) @@ -3350,16 +3353,16 @@ def attempt(): platforms: [linux-32,linux-64,osx-64,win-32,win-64] env_specs: foo: - {packages}: + {pkg_key}: - a bar: - {packages}: + {pkg_key}: - b """ }, check) -def test_unlock_conda_error(packages): +def test_unlock_conda_error(pkg_key): def check(dirname): def attempt(): filename = os.path.join(dirname, DEFAULT_PROJECT_LOCK_FILENAME) @@ -3392,10 +3395,10 @@ def attempt(): platforms: [linux-32,linux-64,osx-64,win-32,win-64] env_specs: foo: - {packages}: + {pkg_key}: - a bar: - {packages}: + {pkg_key}: - b """, DEFAULT_PROJECT_LOCK_FILENAME: f""" @@ -3404,20 +3407,20 @@ def attempt(): foo: locked: true platforms: [linux-32,linux-64,osx-64,win-32,win-64] - {packages}: + {pkg_key}: all: - c bar: locked: true platforms: [linux-32,linux-64,osx-64,win-32,win-64] - {packages}: + {pkg_key}: all: - d """ }, check) -def test_update_unlocked_envs(packages): +def test_update_unlocked_envs(pkg_key): def check(dirname): resolve_results = {'all': ['a=1.0=1']} @@ -3457,17 +3460,17 @@ def attempt(): platforms: [linux-32,linux-64,osx-64,win-32,win-64] env_specs: foo: - {packages}: + {pkg_key}: - a bar: - {packages}: + {pkg_key}: - b """ }, check) @pytest._change_default_pkg_key -def test_update_empty_lock_sets(packages): +def test_update_empty_lock_sets(pkg_key): def check(dirname): resolve_results = {'all': ['a=1.0=1']} @@ -3493,7 +3496,7 @@ def attempt(): '+ linux-64', '+ osx-64', '+ win-64', - f' {packages}:', + f' {pkg_key}:', '+ all:', '+ a=1.0=1', 'Updated locked dependencies for env spec bar in anaconda-project-lock.yml.', @@ -3503,7 +3506,7 @@ def attempt(): '+ linux-64', '+ osx-64', '+ win-64', - f' {packages}:', + f' {pkg_key}:', '+ all:', '+ a=1.0=1', 'Updated locked dependencies for env spec foo in anaconda-project-lock.yml.' @@ -3524,17 +3527,17 @@ def attempt(): platforms: [linux-64,osx-64,win-64] env_specs: foo: - {packages}: + {pkg_key}: - a bar: - {packages}: + {pkg_key}: - b """, DEFAULT_PROJECT_LOCK_FILENAME: "locking_enabled: true\n" }, check) -def test_export_env_spec(packages): +def test_export_env_spec(pkg_key): def check(dirname): project = project_no_dedicated_env(dirname) exported = os.path.join(dirname, "exported.yml") @@ -3546,14 +3549,14 @@ def check(dirname): {"anaconda-project.yml": f""" env_specs: default: - {packages}: + {pkg_key}: - blah channels: - boo """}, check) -def test_export_nonexistent_env_spec(packages): +def test_export_nonexistent_env_spec(pkg_key): def check(dirname): project = project_no_dedicated_env(dirname) exported = os.path.join(dirname, "exported.yml") @@ -3566,14 +3569,14 @@ def check(dirname): {"anaconda-project.yml": f""" env_specs: default: - {packages}: + {pkg_key}: - blah channels: - boo """}, check) -def test_export_env_spec_io_error(monkeypatch, packages): +def test_export_env_spec_io_error(monkeypatch, pkg_key): def check(dirname): project = project_no_dedicated_env(dirname) exported = os.path.join(dirname, "exported.yml") @@ -3591,7 +3594,7 @@ def mock_atomic_replace(*args, **kwargs): {"anaconda-project.yml": f""" env_specs: default: - {packages}: + {pkg_key}: - blah channels: - boo @@ -3638,7 +3641,7 @@ def check(dirname): with_directory_contents_completing_project_file(dict(), check) -def test_add_service_with_env_spec(monkeypatch, packages): +def test_add_service_with_env_spec(monkeypatch, pkg_key): def check(dirname): _monkeypatch_can_connect_to_socket_on_standard_redis_port(monkeypatch) @@ -3658,10 +3661,10 @@ def check(dirname): DEFAULT_PROJECT_FILENAME: f""" env_specs: default: - {packages}: [python] + {pkg_key}: [python] channels: [] myspec: - {packages}: [python] + {pkg_key}: [python] channels: [] """ }, check) @@ -3811,7 +3814,7 @@ def check(dirname): """}, check) -def test_remove_service_with_env_spec(monkeypatch, packages): +def test_remove_service_with_env_spec(monkeypatch, pkg_key): def check(dirname): config_path = ['env_specs', 'myspec', 'services', 'REDIS_URL'] project = project_no_dedicated_env(dirname) @@ -3829,10 +3832,10 @@ def check(dirname): DEFAULT_PROJECT_FILENAME: f""" env_specs: default: - {packages}: [python] + {pkg_key}: [python] channels: [] myspec: - {packages}: [python] + {pkg_key}: [python] channels: [] services: REDIS_URL: redis @@ -4097,7 +4100,7 @@ def check(dirname): with_directory_contents_completing_project_file(dict(), archivetest) -def test_archive_unlocked_warning(packages): +def test_archive_unlocked_warning(pkg_key): def archivetest(archive_dest_dir): archivefile = os.path.join(archive_dest_dir, "foo.zip") @@ -4130,9 +4133,9 @@ def check(dirname): name: archivedproj env_specs: foo: - {packages}: [] + {pkg_key}: [] bar: - {packages}: [] + {pkg_key}: [] """, DEFAULT_PROJECT_LOCK_FILENAME: f""" locking_enabled: false @@ -4140,7 +4143,7 @@ def check(dirname): foo: locked: true platforms: [linux-32,linux-64,osx-64,win-32,win-64] - {packages}: + {pkg_key}: all: [] """, "foo.py": "print('hello')\n" @@ -4565,7 +4568,7 @@ def check(dirname): with_directory_contents(dict(), archivetest) -def test_archive_with_unsaved_project(monkeypatch, packages): +def test_archive_with_unsaved_project(monkeypatch, pkg_key): def archivetest(archive_dest_dir): archivefile = os.path.join(archive_dest_dir, "foo.zip") @@ -4585,7 +4588,7 @@ def check(dirname): {DEFAULT_PROJECT_FILENAME: f""" env_specs: default: - {packages}: [] + {pkg_key}: [] """}, check) with_directory_contents(dict(), archivetest) @@ -4684,7 +4687,7 @@ def check(dirname): @pytest.mark.skipif((sys.version_info.major == 2) and (platform.system() == 'Linux'), reason='Something wrong with pip freeze on linux for py2') @pytest.mark.parametrize('suffix', ['zip', 'tar.bz2', 'tar.gz']) -def test_archive_unarchive_conda_pack_with_pip(suffix, packages): +def test_archive_unarchive_conda_pack_with_pip(suffix, pkg_key): def archivetest(archive_dest_dir): archivefile = os.path.join(archive_dest_dir, "foo.{}".format(suffix)) @@ -4713,7 +4716,7 @@ def check(dirname): with_directory_contents_completing_project_file( {DEFAULT_PROJECT_FILENAME: f""" name: archivedproj -{packages}: +{pkg_key}: - python=3.7 - pip: - pep8 @@ -4724,7 +4727,7 @@ def check(dirname): @pytest.mark.slow @pytest.mark.parametrize('suffix', ['zip', 'tar.bz2', 'tar.gz']) -def test_archive_unarchive_conda_pack(suffix, packages): +def test_archive_unarchive_conda_pack(suffix, pkg_key): def archivetest(archive_dest_dir): archivefile = os.path.join(archive_dest_dir, "foo.{}".format(suffix)) @@ -4802,7 +4805,7 @@ def check(dirname): { DEFAULT_PROJECT_FILENAME: f""" name: archivedproj -{packages}: +{pkg_key}: - font-ttf-ubuntu=0.83=h8b1ccd4_0 """, "foo.py": "print('hello')\n", diff --git a/anaconda_project/yaml_file.py b/anaconda_project/yaml_file.py index b278892e..37584c48 100644 --- a/anaconda_project/yaml_file.py +++ b/anaconda_project/yaml_file.py @@ -139,12 +139,10 @@ def __init__(self, filename): self._change_count = 0 self.load() - # Set `pkg_key` if we have one at the top level of the file, otherwise use - # default. Could look into environments if not defined. Could also raise error - # if both are defined? - for pkg_key in ['dependencies', 'packages']: - if self.get_value(pkg_key): - self.pkg_key = pkg_key + pkg_key = self._get_pkg_key() + if pkg_key: + # Only set if defined, otherwise fallback to the class default. + self.pkg_key = pkg_key def load(self): """Reload the file from disk, discarding any unsaved changes. @@ -207,6 +205,30 @@ def load(self): # pretend we already saved self._previous_content = _dump_string(self._yaml) + def _get_pkg_key(self): + """Return the `pkg_key` ('dependencies' or 'packages') for the file. + + We search for an appropriately named key at the top level, or in the + `env_specs`. Return `None` if none specified. + """ + pkg_key = None + try: + for _pkg_key in ['dependencies', 'packages']: + if self.get_value(_pkg_key): + assert not pkg_key or pkg_key == _pkg_key + pkg_key = _pkg_key + env_specs = self.get_value('env_specs') + if env_specs: + for _spec in env_specs: + for _pkg_key in ['dependencies', 'packages']: + if _pkg_key in env_specs[_spec]: + assert not pkg_key or pkg_key == _pkg_key + pkg_key = _pkg_key + except Exception: + # Don't do error checking here... + pass + return pkg_key + def _load_template(self): # ruamel.yaml returns None if you load an empty file, # so we have to build this ourselves diff --git a/anaconda_project/test/conftest.py b/conftest.py similarity index 84% rename from anaconda_project/test/conftest.py rename to conftest.py index 2795de4d..68fb1196 100644 --- a/anaconda_project/test/conftest.py +++ b/conftest.py @@ -4,7 +4,7 @@ @pytest.fixture(params=["packages", "dependencies"]) -def packages(request): +def pkg_key(request): """Ensure equivalence between `dependencies` and `packages`""" yield request.param @@ -14,7 +14,7 @@ def _change_default_pkg_key(test_function): @functools.wraps(test_function) def wrapper(*v, **kw): - old_pkg_key, YamlFile.pkg_key = YamlFile.pkg_key, kw['packages'] + old_pkg_key, YamlFile.pkg_key = YamlFile.pkg_key, kw['pkg_key'] try: return test_function(*v, **kw) finally: