class ConfWriterTestCase(unittest.TestCase): example_file = "to be ignored \n\ save=true\n\ a_default, another = val \n\ TEST = tobeignored # do you know that thats a comment \n\ test = push \n\ t = \n\ [MakeFiles] \n\ j , ANother = a \n\ multiline \n\ value \n\ ; just a omment \n\ ; just a omment \n" def setUp(self): self.file = os.path.join(tempfile.gettempdir(), "ConfParserTestFile") with open(self.file, "w", encoding='utf-8') as filehandler: filehandler.write(self.example_file) self.conf_parser = ConfParser() self.write_file_name = os.path.join(tempfile.gettempdir(), "ConfWriterTestFile") self.uut = ConfWriter(self.write_file_name) def tearDown(self): os.remove(self.file) os.remove(self.write_file_name) def test_exceptions(self): self.assertRaises(TypeError, self.uut.write_section, 5) def test_write(self): result_file = ["[Default]\n", "save = true\n", "a_default, another = val\n", "# do you know that thats a comment\n", "test = push\n", "t = \n", "\n", "[MakeFiles]\n", "j, ANother = a\n", "multiline\n", "value\n", "; just a omment\n", "; just a omment\n"] self.uut.write_sections(self.conf_parser.reparse(self.file)) del self.uut with open(self.write_file_name, "r") as f: lines = f.readlines() self.assertEqual(result_file, lines)
class ConfParserTestCase(unittest.TestCase): example_file = """to be ignored a_default, another = val TEST = tobeignored # do you know that thats a comment test = push t = [MakeFiles] j , another = a multiline value ; just a omment ; just a omment nokey. = value default.test = content makefiles.lastone = val """ def setUp(self): self.tempdir = tempfile.gettempdir() self.file = os.path.join(self.tempdir, ".coafile") self.nonexistentfile = os.path.join(self.tempdir, "e81k7bd98t") with open(self.file, "w") as filehandler: filehandler.write(self.example_file) self.uut = ConfParser() if sys.version_info < (3, 3): err = OSError else: err = FileNotFoundError try: os.remove(self.nonexistentfile) except err: pass def tearDown(self): os.remove(self.file) def test_parse(self): default_should = OrderedDict([('a_default', 'val'), ('another', 'val'), ('comment0', '# do you know that thats a comment'), ('test', 'content'), ('t', '')]) makefiles_should = OrderedDict([('j', 'a\nmultiline\nvalue'), ('another', 'a\nmultiline\nvalue'), ('comment1', '; just a omment'), ('comment2', '; just a omment'), ('lastone', 'val'), ('comment3', ''), ('a_default', 'val'), ('comment0', '# do you know that thats a comment'), ('test', 'content'), ('t', '')]) self.assertRaises(self.uut.FileNotFoundError, self.uut.parse, self.nonexistentfile) sections = self.uut.parse(self.file) self.assertNotEqual(self.uut.reparse(self.file), sections) key, val = sections.popitem(last=False) self.assertTrue(isinstance(val, Section)) self.assertEqual(key, 'default') is_dict = OrderedDict() for k in val: is_dict[k] = str(val[k]) self.assertEqual(is_dict, default_should) key, val = sections.popitem(last=False) self.assertTrue(isinstance(val, Section)) self.assertEqual(key, 'makefiles') is_dict = OrderedDict() for k in val: is_dict[k] = str(val[k]) self.assertEqual(is_dict, makefiles_should) self.assertEqual(val["comment1"].key, "comment1") self.assertRaises(IndexError, self.uut.get_section, "inexistent section") def test_config_directory(self): self.uut.parse(self.tempdir)
class SectionManager: """ The SectionManager does the following things: - Reading all settings in sections from - Default config - CLI - Configuration file - Collecting all the bears - Filling up all needed settings - Write back the new sections to the configuration file if needed - Give all information back to caller This is done when the run() method is invoked. Anything else is just helper stuff and initialization. """ def __init__(self): self.cli_sections = None self.default_sections = None self.user_sections = None self.coafile_sections = None self.sections = None self.cli_parser = CliParser() self.conf_parser = ConfParser() self.conf_writer = None self.local_bears = {} self.global_bears = {} self.targets = [] def run(self, arg_list=sys.argv[1:]): self._load_configuration(arg_list) self._fill_settings() self._save_configuration() self._warn_nonexistent_targets() return self.sections, self.local_bears, self.global_bears, self.targets def _load_configuration(self, arg_list): self.cli_sections = self.cli_parser.reparse(arg_list=arg_list) # We dont want to store targets argument back to file, thus remove it for item in list( self.cli_sections["default"].contents.pop("targets", "")): self.targets.append(item.lower()) self.default_sections = self._load_config_file( StringConstants.system_coafile) self.user_sections = self._load_config_file( StringConstants.user_coafile, silent=True) default_config = str( self.default_sections["default"].get("config", ".coafile")) user_config = str( self.user_sections["default"].get("config", default_config)) config = os.path.abspath(str( self.cli_sections["default"].get("config", user_config))) self.coafile_sections = self._load_config_file(config) self.sections = self._merge_section_dicts(self.default_sections, self.user_sections) self.sections = self._merge_section_dicts(self.sections, self.coafile_sections) self.sections = self._merge_section_dicts(self.sections, self.cli_sections) for section in self.sections: if section != "default": self.sections[section].defaults = self.sections["default"] def _load_config_file(self, filename, silent=False): """ Loads sections from a config file. Prints an appropriate warning if it doesn't exist and returns a section dict containing an empty default section in that case. It assumes that the cli_sections are available. :param filename: The file to load settings from. :param silent: Whether or not to warn the user if the file doesn't exist. """ filename = os.path.abspath(filename) try: return self.conf_parser.reparse(filename) except self.conf_parser.FileNotFoundError: if not silent: self.cli_sections["default"].retrieve_logging_objects() self.cli_sections["default"].log_printer.warn( _("The requested coafile '{filename}' does not exist. " "Thus it will not be used.").format(filename=filename)) return {"default": Section("default")} def _fill_settings(self): for section_name in self.sections: section = self.sections[section_name] section.retrieve_logging_objects() bear_dirs = path_list(section.get("bear_dirs", "")) bear_dirs.append(os.path.join(StringConstants.coalib_bears_root, "**")) bears = list(section.get("bears", "")) local_bears = collect_bears(bear_dirs, bears, [BEAR_KIND.LOCAL]) global_bears = collect_bears(bear_dirs, bears, [BEAR_KIND.GLOBAL]) filler = SectionFiller(section) all_bears = copy.deepcopy(local_bears) all_bears.extend(global_bears) filler.fill_section(all_bears) self.local_bears[section_name] = local_bears self.global_bears[section_name] = global_bears def _save_configuration(self): self.conf_writer = None default_section = self.sections["default"] try: if bool(default_section.get("save", "false")): self.conf_writer = ConfWriter(str( default_section.get("config", ".coafile"))) except ValueError: self.conf_writer = ConfWriter(str(default_section.get("save", ".coafile"))) if self.conf_writer is not None: self.conf_writer.write_sections(self.sections) @staticmethod def _merge_section_dicts(lower, higher): """ Merges the section dictionaries. The values of higher will take precedence over the ones of lower. Lower will hold the modified dict in the end. """ for name in higher: if name in lower: lower[name].update(higher[name], ignore_defaults=True) else: # no deep copy needed lower[name] = higher[name] return lower def _warn_nonexistent_targets(self): for target in self.targets: if target not in self.sections: self.sections["default"].log_printer.warn( _("The requested section '{section}' is not existent. " "Thus it cannot be executed.").format(section=target))
class SectionManager: """ The SectionManager does the following things: - Reading all settings in sections from - Default config - CLI - Configuration file - Collecting all the bears - Filling up all needed settings - Write back the new sections to the configuration file if needed - Give all information back to caller This is done when the run() method is invoked. Anything else is just helper stuff and initialization. """ def __init__(self): self.cli_sections = None self.default_sections = None self.user_sections = None self.coafile_sections = None self.sections = None self.cli_parser = CliParser() self.conf_parser = ConfParser() self.conf_writer = None self.local_bears = {} self.global_bears = {} self.targets = [] def run(self, arg_list=sys.argv[1:]): self._load_configuration(arg_list) self._fill_settings() self._save_configuration() self._warn_nonexistent_targets() return self.sections, self.local_bears, self.global_bears, self.targets def _load_configuration(self, arg_list): self.cli_sections = self.cli_parser.reparse(arg_list=arg_list) # We dont want to store targets argument back to file, thus remove it for item in list(self.cli_sections["default"].contents.pop( "targets", "")): self.targets.append(item.lower()) self.default_sections = self._load_config_file( StringConstants.system_coafile) self.user_sections = self._load_config_file( StringConstants.user_coafile, silent=True) default_config = str(self.default_sections["default"].get( "config", ".coafile")) user_config = str(self.user_sections["default"].get( "config", default_config)) config = os.path.abspath( str(self.cli_sections["default"].get("config", user_config))) self.coafile_sections = self._load_config_file(config) self.sections = self._merge_section_dicts(self.default_sections, self.user_sections) self.sections = self._merge_section_dicts(self.sections, self.coafile_sections) self.sections = self._merge_section_dicts(self.sections, self.cli_sections) for section in self.sections: if section != "default": self.sections[section].defaults = self.sections["default"] def _load_config_file(self, filename, silent=False): """ Loads sections from a config file. Prints an appropriate warning if it doesn't exist and returns a section dict containing an empty default section in that case. It assumes that the cli_sections are available. :param filename: The file to load settings from. :param silent: Whether or not to warn the user if the file doesn't exist. """ filename = os.path.abspath(filename) try: return self.conf_parser.reparse(filename) except self.conf_parser.FileNotFoundError: if not silent: self.cli_sections["default"].retrieve_logging_objects() self.cli_sections["default"].log_printer.warn( _("The requested coafile '{filename}' does not exist. " "Thus it will not be used.").format(filename=filename)) return {"default": Section("default")} def _fill_settings(self): for section_name in self.sections: section = self.sections[section_name] section.retrieve_logging_objects() bear_dirs = path_list(section.get("bear_dirs", "")) bear_dirs.append( os.path.join(StringConstants.coalib_bears_root, "**")) bears = list(section.get("bears", "")) local_bears = collect_bears(bear_dirs, bears, [BEAR_KIND.LOCAL]) global_bears = collect_bears(bear_dirs, bears, [BEAR_KIND.GLOBAL]) filler = SectionFiller(section) all_bears = copy.deepcopy(local_bears) all_bears.extend(global_bears) filler.fill_section(all_bears) self.local_bears[section_name] = local_bears self.global_bears[section_name] = global_bears def _save_configuration(self): self.conf_writer = None default_section = self.sections["default"] try: if bool(default_section.get("save", "false")): self.conf_writer = ConfWriter( str(default_section.get("config", ".coafile"))) except ValueError: self.conf_writer = ConfWriter( str(default_section.get("save", ".coafile"))) if self.conf_writer is not None: self.conf_writer.write_sections(self.sections) @staticmethod def _merge_section_dicts(lower, higher): """ Merges the section dictionaries. The values of higher will take precedence over the ones of lower. Lower will hold the modified dict in the end. """ for name in higher: if name in lower: lower[name].update(higher[name], ignore_defaults=True) else: # no deep copy needed lower[name] = higher[name] return lower def _warn_nonexistent_targets(self): for target in self.targets: if target not in self.sections: self.sections["default"].log_printer.warn( _("The requested section '{section}' is not existent. " "Thus it cannot be executed.").format(section=target))
class SectionManager: """ The SectionManager does the following things: - Reading all settings in sections from - Default config - CLI - Configuration file - Collecting all the bears - Filling up all needed settings - Write back the new sections to the configuration file if needed - Give all information back to caller This is done when the run() method is invoked. Anything else is just helper stuff and initialization. """ def __init__(self): self.cli_sections = None self.default_section = None self.conf_sections = None self.cli_parser = CliParser() self.conf_parser = ConfParser() self.conf_writer = None self.local_bears = {} self.global_bears = {} def run(self, arg_list=sys.argv[1:]): self._load_configuration(arg_list) self._fill_settings() self._save_configuration() return self.conf_sections, self.local_bears, self.global_bears def _load_configuration(self, arg_list): self.cli_sections = self.cli_parser.reparse(arg_list=arg_list) try: self.default_section = self.conf_parser.reparse( os.path.abspath( os.path.join(StringConstants.coalib_root, "default_coafile")))["default"] except self.conf_parser.FileNotFoundError: self.cli_sections["default"].retrieve_logging_objects() self.cli_sections["default"].log_printer.err( _("The global default coafile for the settings was not found. " "It seems your installation is broken.") + " " + StringConstants.THIS_IS_A_BUG) raise SystemExit for section in self.cli_sections: self.cli_sections[section].defaults = self.default_section try: config = os.path.abspath( str(self.cli_sections["default"].get("config", "./coafile"))) self.conf_sections = self.conf_parser.reparse(config) # We'll get the default section as default section for every section in this dict with this # Furthermore we will have the CLI Values take precedence over the conf values. self._merge_section_dicts() except self.conf_parser.FileNotFoundError: self.conf_sections = self.cli_sections def _fill_settings(self): for section_name in self.conf_sections: section = self.conf_sections[section_name] section.retrieve_logging_objects() local_bears = BearCollector.from_section([BEAR_KIND.LOCAL], section).collect() global_bears = BearCollector.from_section([BEAR_KIND.GLOBAL], section).collect() filler = SectionFiller(section) all_bears = copy.deepcopy(local_bears) all_bears.extend(global_bears) filler.fill_section(all_bears) self.local_bears[section_name] = local_bears self.global_bears[section_name] = global_bears def _save_configuration(self): self.conf_writer = None try: if bool(self.conf_sections["default"]["save"]): self.conf_writer = ConfWriter( str(self.conf_sections["default"]["config"])) except ValueError: self.conf_writer = ConfWriter( str(self.conf_sections["default"]["save"])) if self.conf_writer is not None: self.conf_writer.write_sections(self.conf_sections) def _merge_section_dicts(self): for section_name in self.cli_sections: if section_name in self.conf_sections: self.conf_sections[section_name].update( self.cli_sections[section_name]) else: self.conf_sections[section_name] = self.cli_sections[ section_name] # no deep copy needed