def test_update_raw_config_from_kwargs_falsy_not_none(mock_init): # if kwargs supplies a falsy value, it should not evaluate to null # (ensures code is 'if value is not None' vs. 'if value') config = GalaxyAppConfiguration(property1=0) assert config._raw_config['property1'] == '0' # updated assert type(config._raw_config['property1']) is str # and converted to str
def test_overwrite_reloadable_attribute(mock_init, monkeypatch): # This is similar to test_update_property, but here we overwrite the attribute before reloading. # This can happen if a config property is modified AFTER it has been loaded from schema or kwargs. # For example: load `foo` (from schema or kwargs), but then, in a # subsequent step while initializing # GalaxyAppConfiguration, do something like this: `foo = resove_path(foo, bar)`. Now the value of `foo` # is not what was initially loaded, and if `foo` is reloadable, it will be reset to its default as soon # as the config file is modified. To prevent this, we compare the values read from the modified file # to the `_raw_config` dict. This test ensures this works correctly. # edits to config file: R2 modified monkeypatch.setattr(config, 'read_properties_from_file', lambda _: { R1: 1, R2: 42 }) appconfig = GalaxyAppConfiguration() assert getattr(appconfig, R1) == 1 assert getattr(appconfig, R2) == 2 # overwrite R1 setattr(appconfig, R1, 99) assert getattr(appconfig, R1) == 99 # then reload reload_config_options(appconfig) assert getattr(appconfig, R1) == 99 # no change; should remain overwritten assert getattr(appconfig, R2) == 42 # change: reloadable option modified
def test_resolves_with_empty_component(mock_config, monkeypatch): # A path can be None (root path is never None; may be asigned elsewhere) mock_schema = { 'path0': { 'type': 'str', 'default': 'value0', }, 'path1': { 'type': 'str', 'path_resolves_to': 'path0', }, 'path2': { 'type': 'str', 'default': 'value2', 'path_resolves_to': 'path1', }, } def mock_load_schema(self): self.appschema = mock_schema monkeypatch.setattr(GalaxyAppConfiguration, '_load_schema', mock_load_schema) config = GalaxyAppConfiguration() assert config.path0 == 'value0' assert config.path1 == 'value0' assert config.path2 == 'value0/value2'
def test_resolves_with_empty_component(monkeypatch): # A path can be None (root path is never None; may be asigned elsewhere) mock_schema = { 'path0': { 'type': 'str', 'default': 'value0', }, 'path1': { 'type': 'str', 'path_resolves_to': 'path0', }, 'path2': { 'type': 'str', 'default': 'value2', 'path_resolves_to': 'path1', }, } monkeypatch.setattr(AppSchema, '_read_schema', lambda a, b: get_schema(mock_schema)) monkeypatch.setattr(GalaxyAppConfiguration, '_process_config', lambda a, b: None) monkeypatch.setattr(GalaxyAppConfiguration, '_override_tempdir', lambda a, b: None) config = GalaxyAppConfiguration() assert config.path0 == 'value0' assert config.path1 == 'value0' assert config.path2 == 'value0/value2'
def test_path_resolution_cycle(mock_config, monkeypatch): # Must be a DAG, but this one has a cycle mock_schema = { 'path0': { 'type': 'str', 'default': 'value0', 'path_resolves_to': 'path2', }, 'path1': { 'type': 'str', 'default': 'value1', 'path_resolves_to': 'path0', }, 'path2': { 'type': 'str', 'default': 'value2', 'path_resolves_to': 'path1', }, } def mock_load_schema(self): self.appschema = mock_schema monkeypatch.setattr(GalaxyAppConfiguration, '_load_schema', mock_load_schema) with pytest.raises(ConfigurationError): GalaxyAppConfiguration()
def test_load_default_values(mock_configuration_init): appconfig = GalaxyAppConfiguration() reloadable_config_options = get_reloadable_config_options() assert len(reloadable_config_options) == 14 assert appconfig.message_box_content == reloadable_config_options[ 'message_box_content'] assert appconfig.welcome_url == reloadable_config_options['welcome_url'] assert appconfig.tool_name_boost == reloadable_config_options[ 'tool_name_boost'] assert appconfig.tool_section_boost == reloadable_config_options[ 'tool_section_boost'] assert appconfig.tool_description_boost == reloadable_config_options[ 'tool_description_boost'] assert appconfig.tool_label_boost == reloadable_config_options[ 'tool_label_boost'] assert appconfig.tool_stub_boost == reloadable_config_options[ 'tool_stub_boost'] assert appconfig.tool_help_boost == reloadable_config_options[ 'tool_help_boost'] assert appconfig.tool_search_limit == reloadable_config_options[ 'tool_search_limit'] assert appconfig.tool_enable_ngram_search == reloadable_config_options[ 'tool_enable_ngram_search'] assert appconfig.tool_ngram_minsize == reloadable_config_options[ 'tool_ngram_minsize'] assert appconfig.tool_ngram_maxsize == reloadable_config_options[ 'tool_ngram_maxsize'] assert appconfig.admin_users == reloadable_config_options['admin_users'] assert appconfig.cleanup_job == reloadable_config_options['cleanup_job']
def test_kwargs_relative_path_old_prefix_empty_after_strip(mock_init): # Expect: use value from kwargs, strip old prefix, then resolve new_path1 = 'old-config' config = GalaxyAppConfiguration(path1=new_path1) assert config.path1 == 'my-config/' # stripped of old prefix, then resolved assert config.path2 == 'my-data/my-data-files' # stripped of old prefix, then resolved assert config.path3 == 'my-other-files' # no change
def test_kwargs_set_to_null(mock_init): # Expected: allow overriding with null, then resolve # This is not a common scenario, but it does happen: one example is # `job_config` set to `None` when testing config = GalaxyAppConfiguration(path1=None) assert config.path1 == 'my-config' # resolved assert config.path2 == 'my-data/my-data-files' # resolved assert config.path3 == 'my-other-files' # no change
def test_mock_schema_is_loaded(mock_init): # Check that mock is loaded as expected config = GalaxyAppConfiguration() assert len(config._raw_config) == 5 assert config._raw_config['my_config_dir'] == 'my-config' assert config._raw_config['my_data_dir'] == 'my-data' assert config._raw_config['path1'] == 'my-config-files' assert config._raw_config['path2'] == 'my-data-files' assert config._raw_config['path3'] == 'my-other-files'
def test_kwargs_ablsolute_path(mock_init): # Expected: use value from kwargs, do NOT resolve new_path1 = '/foo1/bar' new_path2 = '/foo2/bar' config = GalaxyAppConfiguration(path1=new_path1, path2=new_path2) assert config.path1 == new_path1 # NOT resolved assert config.path2 == new_path2 # NOT resolved assert config.path3 == 'my-other-files' # no change
def test_kwargs_relative_path_old_prefix(mock_init): # Expect: use value from kwargs, strip old prefix, then resolve new_path1 = 'old-config/foo1/bar' new_path2 = 'old-database/foo2/bar' config = GalaxyAppConfiguration(path1=new_path1, path2=new_path2) assert config.path1 == 'my-config/foo1/bar' # stripped of old prefix, resolved assert config.path2 == 'my-data/foo2/bar' # stripped of old prefix, resolved assert config.path3 == 'my-other-files' # no change
def test_kwargs_relative_path(mock_init): # Expected: use value from kwargs, then resolve new_path1 = 'foo1/bar' new_path2 = 'foo2/bar' config = GalaxyAppConfiguration(path1=new_path1, path2=new_path2) assert config.path1 == 'my-config/' + new_path1 # resolved assert config.path2 == 'my-data/' + new_path2 # resolved assert config.path3 == 'my-other-files' # no change
def test_kwargs_relative_path_old_prefix_for_other_option(mock_init): # Expect: use value from kwargs, do NOT strip old prefix, then resolve # Reason: deprecated dirs are option-specific: we don't want to strip 'old-config' # (deprecated for the config_dir option) if it's used for another option new_path1 = 'old-database/foo1/bar' new_path2 = 'old-config/foo2/bar' config = GalaxyAppConfiguration(path1=new_path1, path2=new_path2) assert config.path1 == 'my-config/' + new_path1 # resolved assert config.path2 == 'my-data/' + new_path2 # resolved assert config.path3 == 'my-other-files' # no change
def test_deprecated_prefixes_set_correctly(monkeypatch): # Before we mock them, check that correct values are assigned monkeypatch.setattr(AppSchema, '_read_schema', lambda a, b: get_schema(MOCK_SCHEMA)) monkeypatch.setattr(GalaxyAppConfiguration, '_process_config', lambda a, b: None) monkeypatch.setattr(GalaxyAppConfiguration, '_override_tempdir', lambda a, b: None) config = GalaxyAppConfiguration() assert config.deprecated_dirs == { 'config_dir': 'config', 'data_dir': 'database' }
def test_update_raw_config_from_kwargs(mock_init): config = GalaxyAppConfiguration(property2=2, property3=2.0, another_key=66) assert len(config._raw_config) == 6 # no change: another_key NOT added assert config._raw_config['property1'] == 'a' # no change assert config._raw_config['property2'] == 2 # updated assert config._raw_config['property3'] == 2.0 # updated assert config._raw_config['property4'] is True # no change assert config._raw_config['property5'] is None # no change assert config._raw_config['property6'] is None # no change assert type(config._raw_config['property1']) is str assert type(config._raw_config['property2']) is int assert type(config._raw_config['property3']) is float assert type(config._raw_config['property4']) is bool
def test_load_config_from_schema(mock_init): config = GalaxyAppConfiguration() assert len(config._raw_config) == 6 assert config._raw_config['property1'] == 'a' assert config._raw_config['property2'] == 1 assert config._raw_config['property3'] == 1.0 assert config._raw_config['property4'] is True assert config._raw_config['property5'] is None assert config._raw_config['property6'] is None assert type(config._raw_config['property1']) is str assert type(config._raw_config['property2']) is int assert type(config._raw_config['property3']) is float assert type(config._raw_config['property4']) is bool
def test_update_raw_config_from_string_kwargs(mock_init): # kwargs may be passed as strings: property data types should not be affected config = GalaxyAppConfiguration(property1='b', property2='2', property3='2.0', property4='false') assert len(config._raw_config) == 6 # no change assert config._raw_config['property1'] == 'b' # updated assert config._raw_config['property2'] == 2 # updated assert config._raw_config['property3'] == 2.0 # updated assert config._raw_config['property4'] is False # updated assert type(config._raw_config['property1']) is str assert type(config._raw_config['property2']) is int assert type(config._raw_config['property3']) is float assert type(config._raw_config['property4']) is bool
def test_deprecated_prefixes_set_correctly(monkeypatch): # Before we mock them, check that correct values are assigned def mock_load_schema(self): self.appschema = {} def mock_process_config(self, kwargs): pass monkeypatch.setattr(GalaxyAppConfiguration, '_load_schema', mock_load_schema) monkeypatch.setattr(GalaxyAppConfiguration, '_process_config', mock_process_config) config = GalaxyAppConfiguration() expected_deprecated_dirs = {'config_dir': 'config', 'data_dir': 'database'} assert config.deprecated_dirs == expected_deprecated_dirs
def test_update_raw_config_from_kwargs_with_none(mock_init): # should be able to set to null regardless of property's datatype config = GalaxyAppConfiguration( property1=None, property2=None, property3=None, property4=None, property5=None, property6=None, ) assert config._raw_config['property1'] is None assert config._raw_config['property2'] is None assert config._raw_config['property3'] is None assert config._raw_config['property4'] is None assert config._raw_config['property5'] is None assert config._raw_config['property6'] is None
def init_models_from_config(config: GalaxyAppConfiguration, map_install_models=False, object_store=None, trace_logger=None): model = init( config.file_path, config.database_connection, config.database_engine_options, map_install_models=map_install_models, database_query_profiling_proxy=config.database_query_profiling_proxy, object_store=object_store, trace_logger=trace_logger, use_pbkdf2=config.get_bool('use_pbkdf2', True), slow_query_log_threshold=config.slow_query_log_threshold, thread_local_log=config.thread_local_log, log_query_counts=config.database_log_query_counts, ) return model
def test_basecase(mock_config, monkeypatch): # Check that a valid graph is loaded correctly (this graph has 2 components) mock_schema = { 'component1_path0': { 'type': 'str', 'default': 'value0', }, 'component1_path1': { 'type': 'str', 'default': 'value1', 'path_resolves_to': 'component1_path0', }, 'component1_path2': { 'type': 'str', 'default': 'value2', 'path_resolves_to': 'component1_path1', }, 'component2_path0': { 'type': 'str', 'default': 'value3', }, 'component2_path1': { 'type': 'str', 'default': 'value4', 'path_resolves_to': 'component2_path0', }, } def mock_load_schema(self): self.appschema = mock_schema monkeypatch.setattr(GalaxyAppConfiguration, '_load_schema', mock_load_schema) config = GalaxyAppConfiguration() assert config.component1_path0 == 'value0' assert config.component1_path1 == 'value0/value1' assert config.component1_path2 == 'value0/value1/value2' assert config.component2_path0 == 'value3' assert config.component2_path1 == 'value3/value4'
def test_basecase(monkeypatch): # Check that a valid graph is loaded correctly (this graph has 2 components) mock_schema = { 'component1_path0': { 'type': 'str', 'default': 'value0', }, 'component1_path1': { 'type': 'str', 'default': 'value1', 'path_resolves_to': 'component1_path0', }, 'component1_path2': { 'type': 'str', 'default': 'value2', 'path_resolves_to': 'component1_path1', }, 'component2_path0': { 'type': 'str', 'default': 'value3', }, 'component2_path1': { 'type': 'str', 'default': 'value4', 'path_resolves_to': 'component2_path0', }, } monkeypatch.setattr(AppSchema, '_read_schema', lambda a, b: get_schema(mock_schema)) monkeypatch.setattr(GalaxyAppConfiguration, '_process_config', lambda a, b: None) monkeypatch.setattr(GalaxyAppConfiguration, '_override_tempdir', lambda a, b: None) config = GalaxyAppConfiguration() assert config.component1_path0 == 'value0' assert config.component1_path1 == 'value0/value1' assert config.component1_path2 == 'value0/value1/value2' assert config.component2_path0 == 'value3' assert config.component2_path1 == 'value3/value4'
def test_resolves_to_invalid_property(mock_config, monkeypatch): # 'path_resolves_to' should point to an existing property in the schema mock_schema = { 'path0': { 'type': 'str', 'default': 'value0', }, 'path1': { 'type': 'str', 'default': 'value1', 'path_resolves_to': 'invalid', # invalid }, } def mock_load_schema(self): self.appschema = mock_schema monkeypatch.setattr(GalaxyAppConfiguration, '_load_schema', mock_load_schema) with pytest.raises(ConfigurationError): GalaxyAppConfiguration()
def test_resolves_to_invalid_type(mock_config, monkeypatch): # Paths should be strings mock_schema = { 'path0': { 'type': 'int', # invalid 'default': 'value0', }, 'path1': { 'type': 'str', 'default': 'value1', 'path_resolves_to': 'path0', }, } def mock_load_schema(self): self.appschema = mock_schema monkeypatch.setattr(GalaxyAppConfiguration, '_load_schema', mock_load_schema) with pytest.raises(ConfigurationError): GalaxyAppConfiguration()
def test_cant_delete_property(mock_init, monkeypatch): # A property should not be deleted: we don't know whether it was initially # set to a default, loaded from a config file, env var, etc. Therefore, if a property # is removed from the config file, it will not be modified or deleted. # edits to config file: R2, N2 deleted monkeypatch.setattr(config, 'read_properties_from_file', lambda _: { R1: 1, N1: 3 }) appconfig = GalaxyAppConfiguration() assert getattr(appconfig, R1) == 1 assert getattr(appconfig, R2) == 2 assert getattr(appconfig, N1) == 3 assert getattr(appconfig, N2) == 4 reload_config_options(appconfig) assert getattr(appconfig, R1) == 1 # no change assert getattr(appconfig, R2) == 2 # no change: option cannot be deleted assert getattr(appconfig, N1) == 3 # no change assert getattr(appconfig, N2) == 4 # no change: option cannot be deleted
def test_update_property(mock_init, monkeypatch): # This also covers adding a property. When a config file does not set a property, # that property is set to its default value. Thus, if we add a reloadable property # to the config file, it's the same as modifying that property's value. # edits to config file: R2, N1 modified monkeypatch.setattr(config, 'read_properties_from_file', lambda _: { R1: 1, R2: 42, N1: 99 }) appconfig = GalaxyAppConfiguration() assert getattr(appconfig, R1) == 1 assert getattr(appconfig, R2) == 2 assert getattr(appconfig, N1) == 3 reload_config_options(appconfig) assert getattr(appconfig, R1) == 1 # no change assert getattr(appconfig, R2) == 42 # change: reloadable option modified assert getattr(appconfig, N1) == 3 # no change: option modified but is non-relodable
def test_update_reloadable_property__message_box_content( mock_configuration_init): appconfig = GalaxyAppConfiguration() appconfig.update_reloadable_property('welcome_url', 'foo') appconfig.update_reloadable_property('message_box_content', 'bar') appconfig.update_reloadable_property('tool_name_boost', 1) appconfig.update_reloadable_property('tool_section_boost', 2) appconfig.update_reloadable_property('tool_description_boost', 3) appconfig.update_reloadable_property('tool_label_boost', 4) appconfig.update_reloadable_property('tool_stub_boost', 5) appconfig.update_reloadable_property('tool_help_boost', 6) appconfig.update_reloadable_property('tool_search_limit', 7) appconfig.update_reloadable_property('tool_enable_ngram_search', True) appconfig.update_reloadable_property('tool_ngram_minsize', 8) appconfig.update_reloadable_property('tool_ngram_maxsize', 9) appconfig.update_reloadable_property( 'admin_users', '[email protected], [email protected]') appconfig.update_reloadable_property('cleanup_job', 'never') assert appconfig.welcome_url == 'foo' assert appconfig.message_box_content == 'bar' assert appconfig.tool_name_boost == 1 assert appconfig.tool_section_boost == 2 assert appconfig.tool_description_boost == 3 assert appconfig.tool_label_boost == 4 assert appconfig.tool_stub_boost == 5 assert appconfig.tool_help_boost == 6 assert appconfig.tool_search_limit == 7 assert appconfig.tool_enable_ngram_search is True assert appconfig.tool_ngram_minsize == 8 assert appconfig.tool_ngram_maxsize == 9 assert appconfig.admin_users == '[email protected], [email protected]' assert appconfig.admin_users_list == [ '*****@*****.**', '*****@*****.**' ] assert appconfig.cleanup_job == 'never'
def test_no_kwargs(mock_init): # Expected: use default from schema, then resolve config = GalaxyAppConfiguration() assert config.path1 == 'my-config/my-config-files' # resolved assert config.path2 == 'my-data/my-data-files' # resolved assert config.path3 == 'my-other-files' # no change
def test_load_value_from_kwargs(mock_configuration_init): appconfig = GalaxyAppConfiguration(welcome_url='foo') assert appconfig.welcome_url == 'foo'