def setUp(self): super().setUp() if not os.path.exists(os.path.dirname(old_config_file())): os.makedirs(os.path.dirname(old_config_file())) with open(old_config_file(), "w") as fh: fh.write(_DUMMY_CFG_INI) if os.path.exists(YTConfig.get_global_config_file()): os.remove(YTConfig.get_global_config_file())
def testConfigMigration(self): self.assertFalse(os.path.exists(YTConfig.get_global_config_file())) self.assertTrue(os.path.exists(old_config_file())) info = self._runYTConfig(["migrate"]) self.assertEqual(info["rc"], 0) self.assertTrue(os.path.exists(YTConfig.get_global_config_file())) self.assertFalse(os.path.exists(old_config_file())) self.assertTrue(os.path.exists(old_config_file() + ".bak")) with open(YTConfig.get_global_config_file()) as fh: new_cfg = fh.read() self.assertEqual(new_cfg, _DUMMY_CFG_TOML)
def load_config(self, args): import os from yt.config import YTConfig from yt.utilities.configure import CONFIG local_config_file = YTConfig.get_local_config_file() global_config_file = YTConfig.get_global_config_file() local_exists = os.path.exists(local_config_file) global_exists = os.path.exists(global_config_file) local_arg_exists = hasattr(args, "local") global_arg_exists = hasattr(args, "global") if getattr(args, "local", False): config_file = local_config_file elif getattr(args, "global", False): config_file = global_config_file else: config_file: Optional[str] = None if local_exists and global_exists: s = ( "Yt detected a local and a global configuration file, refusing " "to proceed.\n" f"Local config file: {local_config_file}\n" f"Global config file: {global_config_file}") # Only print the info about "--global" and "--local" if they exist if local_arg_exists and global_arg_exists: s += ( "\n" # missing eol from previous string "Specify which one you want to use using the `--local` or the " "`--global` flags.") sys.exit(s) elif local_exists: config_file = local_config_file elif global_exists: config_file = global_config_file if config_file is None: print("WARNING: no configuration file installed.", file=sys.stderr) else: print(f"INFO: reading configuration file: {config_file}", file=sys.stderr) CONFIG.read(config_file) self.config_file = config_file
def load_config(self, args): import os from yt.config import YTConfig from yt.utilities.configure import CONFIG local_config_file = YTConfig.get_local_config_file() global_config_file = YTConfig.get_global_config_file() local_exists = os.path.exists(local_config_file) global_exists = os.path.exists(global_config_file) local_arg_exists = hasattr(args, "local") global_arg_exists = hasattr(args, "global") if getattr(args, "local", False): config_file = local_config_file elif getattr(args, "global", False): config_file = global_config_file else: if local_exists and global_exists: s = ( "Yt detected a local and a global configuration file, refusing " "to proceed.\n" f"Local config file: {local_config_file}\n" f"Global config file: {global_config_file}" ) # Only print the info about "--global" and "--local" if they exist if local_arg_exists and global_arg_exists: s += ( "\n" # missing eol from previous string "Specify which one you want to use using the `--local` or the " "`--global` flags." ) sys.exit(s) elif local_exists: config_file = local_config_file else: config_file = global_config_file sys.stderr.write(f"INFO: using configuration file: {config_file}.\n") if not os.path.exists(config_file): with open(config_file, "w") as f: f.write("[yt]\n") CONFIG.read(config_file) self.config_file = config_file
def testConfigCommands(self): def remove_spaces_and_breaks(s): return "".join(s.split()) self.assertFalse(os.path.exists(YTConfig.get_global_config_file())) info = self._runYTConfig(["--help"]) self.assertEqual(info["rc"], 0) self.assertEqual(info["stderr"], "") self.assertIn( remove_spaces_and_breaks( "Get and set configuration values for yt"), remove_spaces_and_breaks(info["stdout"]), ) info = self._runYTConfig(["list"]) self.assertEqual(info["rc"], 0) self.assertEqual(info["stdout"], "") self._testKeyValue("internals.parallel", True, True) self._testKeyValue("test_data_dir", "~/yt-data", os.path.expanduser("~/yt-data")) self._testKeyValue("test_data_dir", "$HOME/yt-data", os.path.expandvars("$HOME/yt-data")) with self.assertRaises(KeyError): self._runYTConfig(["get", "yt", "foo"]) # Check TypeErrors are raised when changing the type of an entry self._testKeyTypeError("foo.bar", "test", 10, expect_error=True) self._testKeyTypeError("foo.bar", "test", False, expect_error=True) # Check no type error are raised when *not* changing the type self._testKeyTypeError("foo.bar", 10, 20, expect_error=False) self._testKeyTypeError("foo.bar", "foo", "bar", expect_error=False)
def setUpModule(): for cfgfile in (GLOBAL_CONFIG_FILE, OLD_CONFIG_FILE, LOCAL_CONFIG_FILE): if os.path.exists(cfgfile): os.rename(cfgfile, cfgfile + ".bak_test") if cfgfile == GLOBAL_CONFIG_FILE: yt.utilities.configure.CONFIG = YTConfig() if not yt.utilities.configure.CONFIG.has_section("yt"): yt.utilities.configure.CONFIG.add_section("yt")
def setUpClass(cls): cls.xdg_config_home = os.environ.get("XDG_CONFIG_HOME") cls.tmpdir = tempfile.mkdtemp() os.environ["XDG_CONFIG_HOME"] = cls.tmpdir with open(YTConfig.get_global_config_file(), mode="w") as fh: fh.write(_DUMMY_CFG_TOML) cls.plugin_path = os.path.join(config_dir(), ytcfg.get("yt", "plugin_filename")) with open(cls.plugin_path, mode="w") as fh: fh.write(TEST_PLUGIN_FILE)
def migrate_config(): if not os.path.exists(old_config_file()): print("Old config not found.") sys.exit(1) old_config = configparser.RawConfigParser() # Preserve case: # See https://stackoverflow.com/questions/1611799/preserve-case-in-configparser old_config.optionxform = str old_config.read(old_config_file()) # In order to migrate, we'll convert everything to lowercase, and map that # to the new snake_case convention def normalize_key(key): return key.replace("_", "").lower() def usesCamelCase(key): if key != key.lower(): return True else: return False old_keys_to_new = {normalize_key(k): k for k in ytcfg_defaults["yt"].keys()} config_as_dict = {} for section in old_config: if section == "DEFAULT": continue config_as_dict[section] = {} for key, value in old_config[section].items(): # Cast value to the most specific type possible cast_value = _cast_value_helper(value) # Normalize the key (if present in the defaults) if normalize_key(key) in old_keys_to_new and section == "yt": new_key = old_keys_to_new[normalize_key(key)] else: new_key = key config_as_dict[section][new_key] = cast_value CONFIG.update(config_as_dict) global_config_file = YTConfig.get_global_config_file() print(f"Writing a new config file to: {global_config_file}") write_config(global_config_file) print(f"Backing up the old config file: {old_config_file()}.bak") os.rename(old_config_file(), old_config_file() + ".bak")
import configparser import os import sys from yt.config import YTConfig, old_config_file, ytcfg_defaults CONFIG = YTConfig() def _cast_bool_helper(value): if value == "True": return True elif value == "False": return False else: raise ValueError("Cannot safely cast to bool") def _expand_all(s): return os.path.expandvars(os.path.expanduser(s)) def _cast_value_helper(value, types=(_cast_bool_helper, int, float, _expand_all)): for t in types: try: retval = t(value) return retval except ValueError: pass
def setUp(self): super().setUp() with open(YTConfig.get_local_config_file(), mode="w") as f: f.writelines("[yt]\n") with open(YTConfig.get_global_config_file(), mode="w") as f: f.writelines("[yt]\n")
def tearDown(self): if os.path.exists(YTConfig.get_global_config_file()): os.remove(YTConfig.get_global_config_file())
import contextlib import os import sys import unittest import unittest.mock as mock from io import StringIO import yt.config import yt.utilities.command_line from yt.config import OLD_CONFIG_FILE, YTConfig GLOBAL_CONFIG_FILE = YTConfig.get_global_config_file() LOCAL_CONFIG_FILE = YTConfig.get_local_config_file() _TEST_PLUGIN = "_test_plugin.py" # NOTE: the normalization of the crazy camel-case will be checked _DUMMY_CFG_INI = f"""[yt] logLevel = 49 pluginfilename = {_TEST_PLUGIN} boolean_stuff = True chunk_size = 3 """ _DUMMY_CFG_TOML = f"""[yt] log_level = 49 plugin_filename = "{_TEST_PLUGIN}" boolean_stuff = true chunk_size = 3 """
def tearDown(self): if os.path.exists(YTConfig.get_global_config_file()): os.remove(YTConfig.get_global_config_file()) if os.path.exists(old_config_file() + ".bak"): os.remove(old_config_file() + ".bak") super().tearDown()