diff --git a/openml/config.py b/openml/config.py index c23fda788..91d7345e0 100644 --- a/openml/config.py +++ b/openml/config.py @@ -38,6 +38,54 @@ connection_n_retries = _defaults['connection_n_retries'] +class ConfigurationForExamples: + """ Allows easy switching to and from a test configuration, used for examples. """ + _last_used_server = None + _last_used_key = None + _start_last_called = False + _test_server = "https://test.openml.org/api/v1/xml" + _test_apikey = "c0c42819af31e706efe1f4b88c23c6c1" + + @classmethod + def start_using_configuration_for_example(cls): + """ Sets the configuration to connect to the test server with valid apikey. + + To configuration as was before this call is stored, and can be recovered + by using the `stop_use_example_configuration` method. + """ + global server + global apikey + + if cls._start_last_called and server == cls._test_server and apikey == cls._test_apikey: + # Method is called more than once in a row without modifying the server or apikey. + # We don't want to save the current test configuration as a last used configuration. + return + + cls._last_used_server = server + cls._last_used_key = apikey + cls._start_last_called = True + + # Test server key for examples + server = cls._test_server + apikey = cls._test_apikey + + @classmethod + def stop_using_configuration_for_example(cls): + """ Return to configuration as it was before `start_use_example_configuration`. """ + if not cls._start_last_called: + # We don't want to allow this because it will (likely) result in the `server` and + # `apikey` variables being set to None. + raise RuntimeError("`stop_use_example_configuration` called without a saved config." + "`start_use_example_configuration` must be called first.") + + global server + global apikey + + server = cls._last_used_server + apikey = cls._last_used_key + cls._start_last_called = False + + def _setup(): """Setup openml package. Called on first import. @@ -140,8 +188,18 @@ def set_cache_directory(cachedir): cache_directory = cachedir +start_using_configuration_for_example = ( + ConfigurationForExamples.start_using_configuration_for_example +) +stop_using_configuration_for_example = ( + ConfigurationForExamples.stop_using_configuration_for_example +) + __all__ = [ - 'get_cache_directory', 'set_cache_directory' + 'get_cache_directory', + 'set_cache_directory', + 'start_using_configuration_for_example', + 'stop_using_configuration_for_example', ] _setup() diff --git a/tests/test_openml/test_config.py b/tests/test_openml/test_config.py index aa2c6d687..44cf4862f 100644 --- a/tests/test_openml/test_config.py +++ b/tests/test_openml/test_config.py @@ -9,3 +9,47 @@ class TestConfig(openml.testing.TestBase): def test_config_loading(self): self.assertTrue(os.path.exists(openml.config.config_file)) self.assertTrue(os.path.isdir(os.path.expanduser('~/.openml'))) + + +class TestConfigurationForExamples(openml.testing.TestBase): + + def test_switch_to_example_configuration(self): + """ Verifies the test configuration is loaded properly. """ + # Below is the default test key which would be used anyway, but just for clarity: + openml.config.apikey = "610344db6388d9ba34f6db45a3cf71de" + openml.config.server = self.production_server + + openml.config.start_using_configuration_for_example() + + self.assertEqual(openml.config.apikey, "c0c42819af31e706efe1f4b88c23c6c1") + self.assertEqual(openml.config.server, self.test_server) + + def test_switch_from_example_configuration(self): + """ Verifies the previous configuration is loaded after stopping. """ + # Below is the default test key which would be used anyway, but just for clarity: + openml.config.apikey = "610344db6388d9ba34f6db45a3cf71de" + openml.config.server = self.production_server + + openml.config.start_using_configuration_for_example() + openml.config.stop_using_configuration_for_example() + + self.assertEqual(openml.config.apikey, "610344db6388d9ba34f6db45a3cf71de") + self.assertEqual(openml.config.server, self.production_server) + + def test_example_configuration_stop_before_start(self): + """ Verifies an error is raised is `stop_...` is called before `start_...`. """ + error_regex = ".*stop_use_example_configuration.*start_use_example_configuration.*first" + self.assertRaisesRegex(RuntimeError, error_regex, + openml.config.stop_using_configuration_for_example) + + def test_example_configuration_start_twice(self): + """ Checks that the original config can be returned to if `start..` is called twice. """ + openml.config.apikey = "610344db6388d9ba34f6db45a3cf71de" + openml.config.server = self.production_server + + openml.config.start_using_configuration_for_example() + openml.config.start_using_configuration_for_example() + openml.config.stop_using_configuration_for_example() + + self.assertEqual(openml.config.apikey, "610344db6388d9ba34f6db45a3cf71de") + self.assertEqual(openml.config.server, self.production_server)