def test_override_compose_two_package_one_group( self, path: str, overrides: List[str], expected: Any ) -> None: config_loader = ConfigLoaderImpl( config_search_path=create_config_search_path(f"{path}/package_tests") ) cfg = config_loader.load_configuration( config_name="two_packages_one_group", overrides=overrides ) with open_dict(cfg): del cfg["hydra"] assert cfg == expected
def test_non_config_group_default() -> None: config_loader = ConfigLoaderImpl( config_search_path=create_config_search_path( "hydra/test_utils/configs")) config_loader.load_configuration( config_name="non_config_group_default.yaml", overrides=[], strict=False) expected = hydra_load_list.copy() expected.extend([ LoadTrace( "non_config_group_default.yaml", "file://hydra/test_utils/configs", "main", None, ), LoadTrace("some_config", "file://hydra/test_utils/configs", "main", None), ]) assert config_loader.get_load_history() == expected
def test_load_adding_group_not_in_default(self, path: str) -> None: config_loader = ConfigLoaderImpl( config_search_path=create_config_search_path(path) ) cfg = config_loader.load_configuration( config_name="optional-default.yaml", overrides=["+group2=file1"], run_mode=RunMode.RUN, ) with open_dict(cfg): del cfg["hydra"] assert cfg == {"foo": 10, "bar": 100}
def test_override_hydra_config_value_from_config_file() -> None: config_loader = ConfigLoaderImpl( config_search_path=create_config_search_path( "hydra/test_utils/configs")) cfg = config_loader.load_configuration( config_name="overriding_output_dir.yaml", overrides=[], strict=False, run_mode=RunMode.RUN, ) assert cfg.hydra.run.dir == "foo"
def test_load_changing_group_in_default(self, path: str) -> None: config_loader = ConfigLoaderImpl( config_search_path=create_config_search_path(path)) cfg = config_loader.load_configuration( config_name="optional-default", overrides=["group1=file2"], strict=False, run_mode=RunMode.RUN, ) with open_dict(cfg): del cfg["hydra"] assert cfg == {"foo": 20}
def test_compose_file_with_dot(self, path: str) -> None: config_loader = ConfigLoaderImpl( config_search_path=create_config_search_path(path) ) cfg = config_loader.load_configuration( config_name="compose.yaml", overrides=["group1=abc.cde"], run_mode=RunMode.RUN, ) with open_dict(cfg): del cfg["hydra"] assert cfg == {"abc=cde": None, "bar": 100}
def test_load_history_with_basic_launcher(self, path: str) -> None: config_loader = ConfigLoaderImpl( config_search_path=create_config_search_path(path) ) config_loader.load_configuration( config_file="custom_default_launcher.yaml", overrides=["hydra/launcher=basic"], strict=False, ) assert config_loader.get_load_history() == [ ("hydra.yaml", "pkg://hydra.conf", "hydra"), ("hydra/hydra_logging/default.yaml", "pkg://hydra.conf", "hydra"), ("hydra/job_logging/default.yaml", "pkg://hydra.conf", "hydra"), ("hydra/launcher/basic.yaml", "pkg://hydra.conf", "hydra"), ("hydra/sweeper/basic.yaml", "pkg://hydra.conf", "hydra"), ("hydra/output/default.yaml", "pkg://hydra.conf", "hydra"), ("hydra/help/default.yaml", "pkg://hydra.conf", "hydra"), ("hydra/hydra_help/default.yaml", "pkg://hydra.conf", "hydra"), ("custom_default_launcher.yaml", path, "main"), ]
def test_load_config_with_validation_error(self, hydra_restore_singletons: Any, path: str) -> None: ConfigStore.instance().store(name="base_mysql", node=MySQLConfig, provider="this_test") config_loader = ConfigLoaderImpl( config_search_path=create_config_search_path(path)) msg = dedent("""\ In 'schema_validation_error': ValidationError raised while composing config: Value 'not_an_int' could not be converted to Integer full_key: port object_type=MySQLConfig""") with raises(ConfigCompositionException, match=re.escape(msg)): config_loader.load_configuration( config_name="schema_validation_error", overrides=[], run_mode=RunMode.RUN, )
def test_load_configuration(self, path: str) -> None: config_loader = ConfigLoaderImpl( config_search_path=create_config_search_path(path) ) cfg = config_loader.load_configuration( config_name="config.yaml", overrides=["+abc=123"], run_mode=RunMode.RUN, ) with open_dict(cfg): del cfg["hydra"] assert cfg == {"normal_yaml_config": True, "abc": 123}
def test_load_with_optional_default(self, path: str) -> None: config_loader = ConfigLoaderImpl( config_search_path=create_config_search_path(path)) cfg = config_loader.load_configuration( config_name="optional-default.yaml", overrides=[], strict=False, run_mode=RunMode.RUN, ) with open_dict(cfg): del cfg["hydra"] assert cfg == {"foo": 10}
def test_overriding_with_dict(config: str, overrides: Any, expected: Any) -> None: config_loader = ConfigLoaderImpl( config_search_path=create_config_search_path( "tests/test_apps/app_with_cfg_groups/conf"), ) cfg = config_loader.load_configuration(config_name=config, overrides=overrides, run_mode=RunMode.RUN) with open_dict(cfg): del cfg["hydra"] assert cfg == expected
def test_overlapping_schemas(restore_singletons: Any) -> None: # noqa: F811 cs = ConfigStore.instance() cs.store(name="config", node=Config) cs.store(group="plugin", name="concrete", node=ConcretePlugin, path="plugin") config_loader = ConfigLoaderImpl(config_search_path=create_config_search_path(None)) cfg = config_loader.load_configuration(config_name="config", overrides=[]) del cfg["hydra"] assert cfg == {"plugin": {"name": "???", "params": "???"}} assert cfg.plugin._type == Plugin cfg = config_loader.load_configuration( config_name="config", overrides=["plugin=concrete"] ) del cfg["hydra"] assert cfg == {"plugin": {"name": "foobar_plugin", "params": {"foo": 10}}} assert cfg.plugin._type == ConcretePlugin assert cfg.plugin.params._type == ConcretePlugin.FoobarParams with pytest.raises(ValidationError): cfg.plugin = 10
def test_override_with_equals(self, path: str) -> None: config_loader = ConfigLoaderImpl( config_search_path=create_config_search_path(path)) cfg = config_loader.load_configuration(config_name="config.yaml", overrides=["abc='cde=12'"], strict=False) with open_dict(cfg): del cfg["hydra"] assert cfg == OmegaConf.create({ "normal_yaml_config": True, "abc": "cde=12" })
def test_load_changing_group_and_package_in_default( self, path: str, overrides: List[str], expected: Any ) -> None: config_loader = ConfigLoaderImpl( config_search_path=create_config_search_path(f"{path}/package_tests") ) cfg = config_loader.load_configuration( config_name="pkg_override", overrides=overrides, run_mode=RunMode.RUN ) with open_dict(cfg): del cfg["hydra"] assert cfg == expected
def test_load_config_with_schema(self, restore_singletons: Any, path: str) -> None: ConfigStore.instance().store( group="db", name="mysql", node=MySQLConfig, path="db", provider="test_provider", ) config_loader = ConfigLoaderImpl( config_search_path=create_config_search_path(path)) cfg = config_loader.load_configuration(config_name="db/mysql", overrides=[]) with open_dict(cfg): del cfg["hydra"] assert cfg == { "db": { "driver": "mysql", "host": "???", "port": "???", "user": "******", "password": "******", } } expected = hydra_load_list.copy() expected.append(LoadTrace("db/mysql", path, "main", "test_provider")) assert config_loader.get_load_history() == expected # verify illegal modification is rejected at runtime with pytest.raises(ValidationError): cfg.db.port = "fail" # verify illegal override is rejected during load with pytest.raises(ValidationError): config_loader.load_configuration(config_name="db/mysql", overrides=["db.port=fail"])
def test_mixed_composition_order() -> None: """ Tests that the order of mixed composition (defaults contains both config group and non config group items) is correct """ config_loader = ConfigLoaderImpl( config_search_path=create_config_search_path( "hydra/test_utils/configs")) config_loader.load_configuration(config_name="mixed_compose.yaml", overrides=[], strict=False) expected = hydra_load_list.copy() expected.extend([ ("mixed_compose.yaml", "file://hydra/test_utils/configs", "main", None), ("some_config", "file://hydra/test_utils/configs", "main", None), ("group1/file1", "file://hydra/test_utils/configs", "main", None), ("config", "file://hydra/test_utils/configs", "main", None), ]) assert config_loader.get_load_history() == expected
def test_complex_defaults(overrides: Any, expected: Any) -> None: config_loader = ConfigLoaderImpl( config_search_path=create_config_search_path( "tests/test_apps/sweep_complex_defaults/conf" ) ) cfg = config_loader.load_configuration( config_name="config", overrides=overrides, run_mode=RunMode.RUN ) with open_dict(cfg): del cfg["hydra"] assert cfg == expected
def test_foo(restore_singletons: Any) -> Any: utils.setup_globals() config_loader = ConfigLoaderImpl( config_search_path=create_config_search_path( "pkg://hydra.test_utils.configs")) cfg = config_loader.load_configuration( config_name="accessing_hydra_config", overrides=[]) HydraConfig.instance().set_config(cfg) with open_dict(cfg): del cfg["hydra"] assert cfg.job_name == "UNKNOWN_NAME" assert cfg.config_name == "accessing_hydra_config"
def test_assign_null( self, restore_singletons: Any, path: str, recwarn: Any ) -> None: config_loader = ConfigLoaderImpl( config_search_path=create_config_search_path(path) ) cfg = config_loader.load_configuration( config_name="config.yaml", overrides=["abc=null"] ) with open_dict(cfg): del cfg["hydra"] assert cfg == {"normal_yaml_config": True, "abc": None} assert len(recwarn) == 0
def test_load_changing_group_in_default(self, path: str, override: str, expected: Dict[Any, Any]) -> None: config_loader = ConfigLoaderImpl( config_search_path=create_config_search_path(path)) cfg = config_loader.load_configuration( config_name="optional-default", overrides=[override], strict=False, run_mode=RunMode.RUN, ) with open_dict(cfg): del cfg["hydra"] assert cfg == expected
def test_mixed_composition_order() -> None: """ Tests that the order of mixed composition (defaults contains both config group and non config group items) is correct """ config_loader = ConfigLoaderImpl( config_search_path=create_config_search_path("hydra/test_utils/configs") ) cfg = config_loader.load_configuration( config_name="mixed_compose.yaml", overrides=[], strict=False, run_mode=RunMode.RUN, ) expected = deepcopy(hydra_load_list) expected.extend( [ LoadTrace( config_path="some_config", package="", parent="mixed_compose.yaml", search_path="file://hydra/test_utils/configs", provider="main", ), LoadTrace( config_path="group1/file1", package="", parent="mixed_compose.yaml", search_path="file://hydra/test_utils/configs", provider="main", ), LoadTrace( config_path="config", package="", parent="mixed_compose.yaml", search_path="file://hydra/test_utils/configs", provider="main", ), LoadTrace( config_path="mixed_compose.yaml", package="", parent="<root>", is_self=True, search_path="file://hydra/test_utils/configs", provider="main", ), ] ) assert_same_composition_trace(cfg.hydra.composition_trace, expected)
def test_load_config_file_with_schema_validation( self, hydra_restore_singletons: Any, path: str ) -> None: with ConfigStoreWithProvider("this_test") as cs: cs.store(name="config", node=TopLevelConfig) cs.store(group="db", name="mysql", node=MySQLConfig, package="db") config_loader = ConfigLoaderImpl( config_search_path=create_config_search_path(path) ) cfg = config_loader.load_configuration( config_name="config", overrides=["+db=mysql"], strict=False, run_mode=RunMode.RUN, ) expected = deepcopy(hydra_load_list) expected.extend( [ LoadTrace( config_path="config", package="", parent="<root>", search_path=path, provider="main", ), LoadTrace( config_path="db/mysql", package="db", parent="<root>", search_path=path, provider="main", ), ] ) assert_same_composition_trace(cfg.hydra.composition_trace, expected) with open_dict(cfg): del cfg["hydra"] assert cfg == { "normal_yaml_config": True, "db": { "driver": "mysql", "host": "???", "port": "???", "user": "******", "password": "******", }, }
def test_load_strict(self, path: str) -> None: """ Ensure that in strict mode we can override only things that are already in the config :return: """ config_loader = ConfigLoaderImpl( config_search_path=create_config_search_path(path)) # Test that overriding existing things works in strict mode cfg = config_loader.load_configuration(config_name="compose.yaml", overrides=["foo=ZZZ"], strict=True) del cfg["hydra"] assert cfg == {"foo": "ZZZ", "bar": 100} # Test that accessing a key that is not there will fail with pytest.raises(AttributeError): # noinspection PyStatementEffect cfg.not_here # Test that bad overrides triggers the KeyError with pytest.raises(AttributeError): config_loader.load_configuration(config_name="compose.yaml", overrides=["f00=ZZZ"], strict=True)
def test_load_history_with_basic_launcher(self, path: str) -> None: config_loader = ConfigLoaderImpl( config_search_path=create_config_search_path(path)) cfg = config_loader.load_configuration( config_name="custom_default_launcher.yaml", overrides=["hydra/launcher=basic"], strict=False, run_mode=RunMode.RUN, ) expected = deepcopy(hydra_load_list) expected.append( LoadTrace( config_name="custom_default_launcher.yaml", search_path=path, provider="main", )) assert_same_composition_trace(cfg.hydra.composition_trace, expected)
def test_load_yml_file(self, path: str) -> None: config_loader = ConfigLoaderImpl( config_search_path=create_config_search_path(path)) with pytest.warns( UserWarning, match= "Support for .yml files is deprecated. Use .yaml extension for Hydra config files", ): cfg = config_loader.load_configuration( config_name="config.yml", overrides=[], run_mode=RunMode.RUN, ) with open_dict(cfg): del cfg["hydra"] assert cfg == {"yml_file_here": True}
def test_load_history(self, path: str) -> None: config_loader = ConfigLoaderImpl( config_search_path=create_config_search_path(path)) cfg = config_loader.load_configuration( config_name="missing-optional-default.yaml", overrides=[], run_mode=RunMode.RUN, ) expected = deepcopy(hydra_load_list) expected.append( LoadTrace( config_path="missing-optional-default.yaml", package="", parent="<root>", is_self=True, search_path=path, provider="main", )) assert_same_composition_trace(cfg.hydra.composition_trace, expected)
def test_load_schema_as_config(hydra_restore_singletons: Any) -> None: """ Load structured config as a configuration """ ConfigStore.instance().store( name="config", node=TopLevelConfig, provider="this_test" ) ConfigStore.instance().store( name="db/mysql", node=MySQLConfig, provider="this_test" ) config_loader = ConfigLoaderImpl(config_search_path=create_config_search_path(None)) cfg = config_loader.load_configuration( config_name="config", overrides=[], run_mode=RunMode.RUN ) expected = deepcopy(hydra_load_list) expected.append( LoadTrace( config_path="config", package="", parent="<root>", search_path="structured://", provider="this_test", ) ) assert_same_composition_trace(cfg.hydra.composition_trace, expected) with open_dict(cfg): del cfg["hydra"] assert cfg == { "normal_yaml_config": "???", "db": { "driver": MISSING, "host": MISSING, "port": MISSING, "user": MISSING, "password": MISSING, }, }
def test_default_removal(config_file: str, overrides: List[str]) -> None: config_loader = ConfigLoaderImpl( config_search_path=create_config_search_path("hydra/test_utils/configs") ) cfg = config_loader.load_configuration( config_name=config_file, overrides=overrides, strict=False, run_mode=RunMode.RUN ) expected = deepcopy(hydra_load_list) for x in expected: if x.config_group == "hydra/launcher": x.skip_reason = "deleted_from_list" x.search_path = None x.provider = None expected.append( LoadTrace( config_name=config_file, search_path="file://hydra/test_utils/configs", provider="main", ) ) assert_same_composition_trace(cfg.hydra.composition_trace, expected)
def test_default_removal(config_file: str, overrides: List[str]) -> None: config_loader = ConfigLoaderImpl( config_search_path=create_config_search_path("hydra/test_utils/configs") ) cfg = config_loader.load_configuration( config_name=config_file, overrides=overrides, strict=False, run_mode=RunMode.RUN ) expected = deepcopy(hydra_load_list) expected = list( filterfalse(lambda x: x.config_path == "hydra/launcher/basic", expected) ) expected.append( LoadTrace( config_path=config_file, package="", parent="<root>", search_path="file://hydra/test_utils/configs", provider="main", ) ) assert_same_composition_trace(cfg.hydra.composition_trace, expected)
def test_sweep_config_cache(self, hydra_restore_singletons: Any, path: str, monkeypatch: Any) -> None: setup_globals() monkeypatch.setenv("TEST_ENV", "test_env") config_loader = ConfigLoaderImpl( config_search_path=create_config_search_path(path)) master_cfg = config_loader.load_configuration( config_name="config.yaml", overrides=[ "+time=${now:%H-%M-%S}", "+test_env=${oc.env:TEST_ENV}" ], run_mode=RunMode.RUN, ) # trigger resolution by type assertion assert type(master_cfg.time) == str assert type(master_cfg.test_env) == str master_cfg_cache = OmegaConf.get_cache(master_cfg) assert "now" in master_cfg_cache.keys() # oc.env is not cached as of OmegaConf 2.1 assert "oc.env" not in master_cfg_cache.keys() assert master_cfg.test_env == "test_env" sweep_cfg = config_loader.load_sweep_config( master_config=master_cfg, sweep_overrides=[ "+time=${now:%H-%M-%S}", "+test_env=${oc.env:TEST_ENV}" ], ) sweep_cfg_cache = OmegaConf.get_cache(sweep_cfg) assert len( sweep_cfg_cache.keys()) == 1 and "now" in sweep_cfg_cache.keys() assert sweep_cfg_cache["now"] == master_cfg_cache["now"] monkeypatch.setenv("TEST_ENV", "test_env2") assert sweep_cfg.test_env == "test_env2"