def setUp(self): self.file = os.path.join(tempfile.gettempdir(), "ConfParserTestFile") with open(self.file, "w", encoding='utf-8') as file: file.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 __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 load(cls, language: str, docstyle: str, coalang_dir=None): """ Loads a ``DocstyleDefinition`` from the coala docstyle definition files. This function considers all settings inside the according coalang-files as markers. :param language: The case insensitive programming language of the documentation comment as a string. :param docstyle: The case insensitive documentation style/tool used to document code, e.g. ``"default"`` or ``"doxygen"``. :param coalang_dir: Path to directory with coalang docstyle definition files. This replaces the default path if given. :raises FileNotFoundError: Raised when the given docstyle was not found. :raises KeyError: Raised when the given language is not defined for given docstyle. :return: The ``DocstyleDefinition`` for given language and docstyle. """ docstyle = docstyle.lower() language_config_parser = ConfParser(remove_empty_iter_elements=False) coalang_file = os.path.join( coalang_dir or os.path.dirname(__file__), docstyle + ".coalang") try: docstyle_settings = language_config_parser.parse(coalang_file) except FileNotFoundError: raise FileNotFoundError("Docstyle definition " + repr(docstyle) + " not found.") language = language.lower() try: docstyle_settings = docstyle_settings[language] except KeyError: raise KeyError("Language {!r} is not defined for docstyle {!r}." .format(language, docstyle)) marker_sets = (tuple(value) for key, value in filter(lambda kv: not kv[0].startswith("comment"), docstyle_settings.contents.items())) return cls(language, docstyle, marker_sets)
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 file: file.write(self.example_file) self.uut = ConfParser() try: os.remove(self.nonexistentfile) except FileNotFoundError: pass self.sections = self.uut.parse(self.file)
def load(cls, language: str, docstyle: str, coalang_dir=None): """ Loads a ``DocstyleDefinition`` from the coala docstyle definition files. This function considers all settings inside the according coalang-files as markers. :param language: The case insensitive programming language of the documentation comment as a string. :param docstyle: The case insensitive documentation style/tool used to document code, e.g. ``"default"`` or ``"doxygen"``. :param coalang_dir: Path to directory with coalang docstyle definition files. This replaces the default path if given. :raises FileNotFoundError: Raised when the given docstyle was not found. :raises KeyError: Raised when the given language is not defined for given docstyle. :return: The ``DocstyleDefinition`` for given language and docstyle. """ docstyle = docstyle.lower() language_config_parser = ConfParser(remove_empty_iter_elements=False) coalang_file = os.path.join(coalang_dir or os.path.dirname(__file__), docstyle + ".coalang") try: docstyle_settings = language_config_parser.parse(coalang_file) except FileNotFoundError: raise FileNotFoundError("Docstyle definition " + repr(docstyle) + " not found.") language = language.lower() try: docstyle_settings = docstyle_settings[language] except KeyError: raise KeyError( "Language {!r} is not defined for docstyle {!r}.".format( language, docstyle)) marker_sets = (tuple(value) for key, value in filter( lambda kv: not kv[0].startswith("comment"), docstyle_settings.contents.items())) return cls(language, docstyle, marker_sets)
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 load_config_file(filename, log_printer, 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 log_printer: The log printer to log the warning/error to (in case). :param silent: Whether or not to warn the user/exit if the file doesn't exist. :raises SystemExit: Exits when given filename is invalid and is not the default coafile. Only raised when `silent` is `False`. """ filename = os.path.abspath(filename) try: return ConfParser().parse(filename) except FileNotFoundError: if not silent: if os.path.basename(filename) == Constants.default_coafile: log_printer.warn("The default coafile " + repr(Constants.default_coafile) + " was not " "found. Ignoring it.") else: log_printer.err("The requested coafile " + repr(filename) + " does not exist.") sys.exit(2) return {"default": Section("default")}
def get_available_definitions(): """ Returns a sequence of pairs with ``(docstyle, language)`` which are available when using ``load()``. :return: A sequence of pairs with ``(docstyle, language)``. """ language_config_parser = ConfParser(remove_empty_iter_elements=False) pattern = os.path.join(os.path.dirname(__file__), '*.coalang') for coalang_file in iglob(pattern): docstyle = os.path.splitext(os.path.basename(coalang_file))[0] # Ignore files that are not lowercase, as coalang files have to be. if docstyle.lower() == docstyle: for language in language_config_parser.parse(coalang_file): yield docstyle, language.lower()
def load_config_file(filename, log_printer=None, 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 log_printer: The log printer to log the warning/error to (in case). :param silent: Whether or not to warn the user/exit if the file doesn't exist. :raises SystemExit: Exits when the given filename is invalid and is not the default coafile. Only raised when ``silent`` is ``False``. """ filename = os.path.abspath(filename) try: return ConfParser().parse(filename) except FileNotFoundError: if not silent: if os.path.basename(filename) == Constants.default_coafile: logging.warning( COAFILE_OUTPUT.substitute(type='Default coafile', file=Constants.default_coafile, found='not found')) else: logging.error( COAFILE_OUTPUT.substitute(type='Requested coafile', file=filename, found='does not exist')) sys.exit(2) return {'default': Section('default')}
def load_config_file(filename, log_printer, 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 log_printer: The log printer to log the warning/error to (in case). :param silent: Whether or not to warn the user/exit if the file doesn't exist. :raises SystemExit: Exits when the given filename is invalid and is not the default coafile. Only raised when ``silent`` is ``False``. """ filename = os.path.abspath(filename) try: return ConfParser().parse(filename) except FileNotFoundError: if not silent: if os.path.basename(filename) == Constants.default_coafile: log_printer.warn("The default coafile {0!r} was not found. " "You can generate a configuration file with " "your current options by adding the `--save` " "flag.".format(Constants.default_coafile)) else: log_printer.err( "The requested coafile {0!r} does not exist. " "You can generate it with your current " "options by adding the `--save` flag.".format(filename)) sys.exit(2) return {"default": Section("default")}
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 setUp(self): self.file = os.path.join(tempfile.gettempdir(), "ConfParserTestFile") with open(self.file, "w", encoding="utf-8") as file: file.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)
class ConfWriterTest(unittest.TestCase): example_file = ("to be ignored \n" " save=true\n" " a_default, another = val \n" " TEST = tobeignored # thats a comment \n" " test = push \n" " t = \n" " [Section] \n" " [MakeFiles] \n" " j , ANother = a \n" " multiline \n" " value \n" " ; just a omment \n" " ; just a omment \n" " key\\ space = value space\n" " key\\=equal = value=equal\n" " key\\\\backslash = value\\\\backslash\n" " key\\,comma = value,comma\n" " key\\#hash = value\\#hash\n" " key\\.dot = value.dot\n") def setUp(self): self.file = os.path.join(tempfile.gettempdir(), "ConfParserTestFile") with open(self.file, "w", encoding='utf-8') as file: file.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): self.uut.close() 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", "# thats a comment\n", "test = push\n", "t = \n", "[Section]\n", "[MakeFiles]\n", "j, ANother = a\n", "multiline\n", "value\n", "; just a omment\n", "; just a omment\n", "key\\ space = value space\n", "key\\=equal = value=equal\n", "key\\\\backslash = value\\\\backslash\n", "key\\,comma = value,comma\n", "key\\#hash = value\\#hash\n", "key\\.dot = value.dot\n" ] self.uut.write_sections(self.conf_parser.parse(self.file)) self.uut.close() with open(self.write_file_name, "r") as f: lines = f.readlines() self.assertEqual(result_file, lines)
def test_warning_typo(self): logger = logging.getLogger() with self.assertLogs(logger, 'WARNING') as cm: newConf = ConfParser(comment_seperators=('#', )) self.assertEquals( cm.output[0], 'WARNING:root:The setting ' '`comment_seperators` is deprecated. ' 'Please use `comment_separators` ' 'instead.')
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 file: file.write(self.example_file) self.uut = ConfParser() try: os.remove(self.nonexistentfile) except FileNotFoundError: pass logger = logging.getLogger() isnotdir = mock.Mock(return_value=False) with self.assertLogs(logger, 'WARNING') as self.cm: with mock.patch('os.path.isdir', isnotdir): self.sections = self.uut.parse(self.file)
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() try: os.remove(self.nonexistentfile) except FileNotFoundError: pass
class ConfWriterTest(unittest.TestCase): example_file = ("to be ignored \n" " save=true\n" " a_default, another = val \n" " TEST = tobeignored # 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): self.uut.close() 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", "# 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.parse(self.file)) self.uut.close() with open(self.write_file_name, "r") as f: lines = f.readlines() self.assertEqual(result_file, lines)
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)
def test_run(self): defaults = ConfParser().parse( os.path.abspath( os.path.join(StringConstants.coalib_root, "default_coafile"))) uut = SectionManager() # We need to use a bad filename or this will parse the .coafile we use for coala conf_sections = uut.run( arg_list=['-S', "test=5", "-c", "some_bad_filename"])[0] self.assertEqual(str(conf_sections["default"]), "Default {config : some_bad_filename, test : 5}") self.assertEqual(str(conf_sections["default"].defaults), str(defaults["default"]))
def __init__(self, language: str, coalang_dir=None): """ Creates a new LanguageDefinition object from file. A Language Definition holds constants which may help parsing the language. If you want to write a bear you'll probably want to use those definitions to keep your bear independent of the semantics of each language. You can easily get your language definition by just creating it with the name of the language desired: >>> list(LanguageDefinition("cpp")['extensions']) ['.c', '.cpp', '.h', '.hpp'] For some languages aliases exist, the name is case insensitive: >>> list(LanguageDefinition("C++")['extensions']) ['.c', '.cpp', '.h', '.hpp'] If no language exists, you will get a ``FileNotFoundError``: >>> LanguageDefinition("BULLSHIT!") # +ELLIPSIS Traceback (most recent call last): ... FileNotFoundError: ... :param language: The actual language (e.g. C++). :param coalang_dir: Path to directory with coalang language definition files. This replaces the default path if given. :raises FileNotFoundError: Raised when no definition is available for the given language. """ SectionCreatable.__init__(self) self.language = language.lower() if self.language in LANGUAGE_DICT: self.language = LANGUAGE_DICT[self.language] coalang_file = os.path.join( coalang_dir or Constants.language_definitions, self.language + ".coalang") self.lang_dict = ConfParser().parse(coalang_file)["default"]
def __init__(self, language: str): """ Creates a new LanguageDefinition object from file. A Language Definition holds constants which may help parsing the language. If you want to write a bear you'll probably want to use those definitions to keep your bear independent of the semantics of each language. :param language: The actual language (e.g. C++). :raises FileNotFoundError: Raised when no definition is available for the given family. :raises KeyError: Raised when no definition is available for the given language. """ SectionCreatable.__init__(self) self.language = language.lower() filename = os.path.join(Constants.language_definitions, language.lower() + ".coalang") self.lang_dict = ConfParser().parse(filename)["default"]
def __init__(self, language: str, coalang_dir=None): """ Creates a new LanguageDefinition object from file. A Language Definition holds constants which may help parsing the language. If you want to write a bear you'll probably want to use those definitions to keep your bear independent of the semantics of each language. :param language: The actual language (e.g. C++). :param coalang_dir: Path to directory with coalang language definition files. This replaces the default path if given. :raises FileNotFoundError: Raised when no definition is available for the given language. """ SectionCreatable.__init__(self) self.language = language.lower() coalang_file = os.path.join( coalang_dir or Constants.language_definitions, self.language + ".coalang") self.lang_dict = ConfParser().parse(coalang_file)["default"]
class ConfParserTest(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 [EMPTY_ELEM_STRIP] A = a, b, c B = a, ,, d C = ,,, """ 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() try: os.remove(self.nonexistentfile) except FileNotFoundError: pass self.sections = self.uut.parse(self.file) def tearDown(self): os.remove(self.file) def test_parse_nonexisting_file(self): self.assertRaises(FileNotFoundError, self.uut.parse, self.nonexistentfile) self.assertNotEqual(self.uut.parse(self.file, True), self.sections) def test_parse_nonexisting_section(self): self.assertRaises(IndexError, self.uut.get_section, "inexistent section") def test_parse_default_section(self): default_should = OrderedDict([ ('a_default', 'val'), ('another', 'val'), ('comment0', '# do you know that thats a comment'), ('test', 'content'), ('t', '')]) key, val = self.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) def test_parse_makefiles_section(self): 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', '')]) # Pop off the default section. self.sections.popitem(last=False) key, val = self.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") def test_parse_empty_elem_strip_section(self): empty_elem_strip_should = OrderedDict([ ('a', 'a, b, c'), ('b', 'a, ,, d'), ('c', ',,,'), ('comment4', ''), ('a_default', 'val'), ('another', 'val'), ('comment0', '# do you know that thats a comment'), ('test', 'content'), ('t', '')]) # Pop off the default and makefiles section. self.sections.popitem(last=False) self.sections.popitem(last=False) key, val = self.sections.popitem(last=False) self.assertTrue(isinstance(val, Section)) self.assertEqual(key, 'empty_elem_strip') is_dict = OrderedDict() for k in val: is_dict[k] = str(val[k]) self.assertEqual(is_dict, empty_elem_strip_should) def test_remove_empty_iter_elements(self): # Test with empty-elem stripping. uut = ConfParser(remove_empty_iter_elements=True) uut.parse(self.file) self.assertEqual(list(uut.get_section("EMPTY_ELEM_STRIP")["A"]), ["a", "b", "c"]) self.assertEqual(list(uut.get_section("EMPTY_ELEM_STRIP")["B"]), ["a", "d"]) self.assertEqual(list(uut.get_section("EMPTY_ELEM_STRIP")["C"]), []) # Test without stripping. uut = ConfParser(remove_empty_iter_elements=False) uut.parse(self.file) self.assertEqual(list(uut.get_section("EMPTY_ELEM_STRIP")["A"]), ["a", "b", "c"]) self.assertEqual(list(uut.get_section("EMPTY_ELEM_STRIP")["B"]), ["a", "", "", "d"]) self.assertEqual(list(uut.get_section("EMPTY_ELEM_STRIP")["C"]), ["", "", "", ""]) 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 ConfParserTest(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 [EMPTY_ELEM_STRIP] A = a, b, c B = a, ,, d C = ,,, """ 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() try: os.remove(self.nonexistentfile) except FileNotFoundError: pass self.sections = self.uut.parse(self.file) def tearDown(self): os.remove(self.file) def test_parse_nonexisting_file(self): self.assertRaises(FileNotFoundError, self.uut.parse, self.nonexistentfile) self.assertNotEqual(self.uut.parse(self.file, True), self.sections) def test_parse_nonexisting_section(self): self.assertRaises(IndexError, self.uut.get_section, "inexistent section") def test_parse_default_section(self): default_should = OrderedDict([('a_default', 'val'), ('another', 'val'), ('comment0', '# do you know that thats a comment'), ('test', 'content'), ('t', '')]) key, val = self.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) def test_parse_makefiles_section(self): 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', '')]) # Pop off the default section. self.sections.popitem(last=False) key, val = self.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") def test_parse_empty_elem_strip_section(self): empty_elem_strip_should = OrderedDict([ ('a', 'a, b, c'), ('b', 'a, ,, d'), ('c', ',,,'), ('comment4', ''), ('a_default', 'val'), ('another', 'val'), ('comment0', '# do you know that thats a comment'), ('test', 'content'), ('t', '') ]) # Pop off the default and makefiles section. self.sections.popitem(last=False) self.sections.popitem(last=False) key, val = self.sections.popitem(last=False) self.assertTrue(isinstance(val, Section)) self.assertEqual(key, 'empty_elem_strip') is_dict = OrderedDict() for k in val: is_dict[k] = str(val[k]) self.assertEqual(is_dict, empty_elem_strip_should) def test_remove_empty_iter_elements(self): # Test with empty-elem stripping. uut = ConfParser(remove_empty_iter_elements=True) uut.parse(self.file) self.assertEqual(list(uut.get_section("EMPTY_ELEM_STRIP")["A"]), ["a", "b", "c"]) self.assertEqual(list(uut.get_section("EMPTY_ELEM_STRIP")["B"]), ["a", "d"]) self.assertEqual(list(uut.get_section("EMPTY_ELEM_STRIP")["C"]), []) # Test without stripping. uut = ConfParser(remove_empty_iter_elements=False) uut.parse(self.file) self.assertEqual(list(uut.get_section("EMPTY_ELEM_STRIP")["A"]), ["a", "b", "c"]) self.assertEqual(list(uut.get_section("EMPTY_ELEM_STRIP")["B"]), ["a", "", "", "d"]) self.assertEqual(list(uut.get_section("EMPTY_ELEM_STRIP")["C"]), ["", "", "", ""]) def test_config_directory(self): self.uut.parse(self.tempdir)
class ConfWriterTest(unittest.TestCase): example_file = ('to be ignored \n' ' save=true\n' ' a_default, another = val \n' ' TEST = tobeignored # thats a comment \n' ' test = push \n' ' t = \n' ' [Section] \n' ' [MakeFiles] \n' ' j , ANother = a \n' ' multiline \n' ' value \n' ' ; just a omment \n' ' ; just a omment \n' ' key\\ space = value space\n' ' key\\=equal = value=equal\n' ' key\\\\backslash = value\\\\backslash\n' ' key\\,comma = value,comma\n' ' key\\#hash = value\\#hash\n' ' key\\.dot = value.dot\n') def setUp(self): self.file = os.path.join(tempfile.gettempdir(), 'ConfParserTestFile') with open(self.file, 'w', encoding='utf-8') as file: file.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): self.uut.close() 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', '# thats a comment\n', 'test = push\n', 't = \n', '[Section]\n', '[MakeFiles]\n', 'j, ANother = a\n', 'multiline\n', 'value\n', '; just a omment\n', '; just a omment\n', 'key\\ space = value space\n', 'key\\=equal = value=equal\n', 'key\\\\backslash = value\\\\backslash\n', 'key\\,comma = value,comma\n', 'key\\#hash = value\\#hash\n', 'key\\.dot = value.dot\n'] self.uut.write_sections(self.conf_parser.parse(self.file)) self.uut.close() with open(self.write_file_name, 'r') as f: lines = f.readlines() self.assertEqual(result_file, lines)
def load(cls, language: str, docstyle: str, coalang_dir=None): """ Loads a ``DocstyleDefinition`` from the coala docstyle definition files. This function considers all settings inside the according coalang-files as markers, except ``param_start``, ``param_end`` and ``return_sep`` which are considered as special metadata markers. .. note:: When placing new coala docstyle definition files, these must consist of only lowercase letters and end with ``.coalang``! :param language: The case insensitive programming language of the documentation comment as a string. :param docstyle: The case insensitive documentation style/tool used to document code, e.g. ``"default"`` or ``"doxygen"``. :param coalang_dir: Path to directory with coalang docstyle definition files. This replaces the default path if given. :raises FileNotFoundError: Raised when the given docstyle was not found. :raises KeyError: Raised when the given language is not defined for given docstyle. :return: The ``DocstyleDefinition`` for given language and docstyle. """ docstyle = docstyle.lower() language_config_parser = ConfParser(remove_empty_iter_elements=False) coalang_file = os.path.join( coalang_dir or os.path.dirname(__file__), docstyle + '.coalang') try: docstyle_settings = language_config_parser.parse(coalang_file) except FileNotFoundError: raise FileNotFoundError('Docstyle definition ' + repr(docstyle) + ' not found.') language = language.lower() try: docstyle_settings = docstyle_settings[language] except KeyError: raise KeyError('Language {!r} is not defined for docstyle {!r}.' .format(language, docstyle)) metadata_settings = ('param_start', 'param_end', 'return_sep') metadata = cls.Metadata(*(str(docstyle_settings.get(req_setting, '')) for req_setting in metadata_settings)) marker_sets = (tuple(value) for key, value in docstyle_settings.contents.items() if key not in metadata_settings and not key.startswith('comment')) return cls(language, docstyle, marker_sets, metadata)
def test_remove_empty_iter_elements(self): # Test with empty-elem stripping. uut = ConfParser(remove_empty_iter_elements=True) uut.parse(self.file) self.assertEqual(list(uut.get_section("EMPTY_ELEM_STRIP")["A"]), ["a", "b", "c"]) self.assertEqual(list(uut.get_section("EMPTY_ELEM_STRIP")["B"]), ["a", "d"]) self.assertEqual(list(uut.get_section("EMPTY_ELEM_STRIP")["C"]), []) # Test without stripping. uut = ConfParser(remove_empty_iter_elements=False) uut.parse(self.file) self.assertEqual(list(uut.get_section("EMPTY_ELEM_STRIP")["A"]), ["a", "b", "c"]) self.assertEqual(list(uut.get_section("EMPTY_ELEM_STRIP")["B"]), ["a", "", "", "d"]) self.assertEqual(list(uut.get_section("EMPTY_ELEM_STRIP")["C"]), ["", "", "", ""])
class ConfParserTest(unittest.TestCase): example_file = """setting = without_section [foo] to be ignored a_default, another = val TEST = tobeignored # do you know that thats a comment test = push t = escaped_\\=equal = escaped_\\#hash escaped_\\\\backslash = escaped_\\ space escaped_\\,comma = escaped_\\.dot [MakeFiles] j , another = a multiline value # just a comment # just a comment nokey. = value foo.test = content makefiles.lastone = val append += key [EMPTY_ELEM_STRIP] A = a, b, c B = a, ,, d C = ,,, [name] key1 = value1 key2 = value1 key1 = value2 """ 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 file: file.write(self.example_file) self.uut = ConfParser() try: os.remove(self.nonexistentfile) except FileNotFoundError: pass logger = logging.getLogger() with self.assertLogs(logger, 'WARNING') as self.cm: self.sections = self.uut.parse(self.file) def tearDown(self): os.remove(self.file) def test_warning_typo(self): logger = logging.getLogger() with self.assertLogs(logger, 'WARNING') as cm: newConf = ConfParser(comment_seperators=('#',)) self.assertEquals(cm.output[0], 'WARNING:root:The setting ' '`comment_seperators` is deprecated. ' 'Please use `comment_separators` ' 'instead.') def test_parse_nonexisting_file(self): self.assertRaises(FileNotFoundError, self.uut.parse, self.nonexistentfile) self.assertNotEqual(self.uut.parse(self.file, True), self.sections) def test_parse_nonexisting_section(self): self.assertRaises(IndexError, self.uut.get_section, 'non-existent section') def test_parse_default_section_deprecated(self): default_should = OrderedDict([ ('setting', 'without_section')]) key, val = self.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) self.assertRegex(self.cm.output[0], 'A setting does not have a section.') # Check if line number is correctly set when # no section is given line_num = val.contents['setting'].line_number self.assertEqual(line_num, 1) def test_parse_foo_section(self): foo_should = OrderedDict([ ('a_default', 'val'), ('another', 'val'), ('comment0', '# do you know that thats a comment'), ('test', 'content'), ('t', ''), ('escaped_=equal', 'escaped_#hash'), ('escaped_\\backslash', 'escaped_ space'), ('escaped_,comma', 'escaped_.dot')]) # Pop off the default section. self.sections.popitem(last=False) key, val = self.sections.popitem(last=False) self.assertTrue(isinstance(val, Section)) self.assertEqual(key, 'foo') is_dict = OrderedDict() for k in val: is_dict[k] = str(val[k]) self.assertEqual(is_dict, foo_should) def test_parse_makefiles_section(self): makefiles_should = OrderedDict([ ('j', 'a\nmultiline\nvalue'), ('another', 'a\nmultiline\nvalue'), ('comment1', '# just a comment'), ('comment2', '# just a comment'), ('lastone', 'val'), ('append', 'key'), ('comment3', '')]) # Pop off the default and foo section. self.sections.popitem(last=False) self.sections.popitem(last=False) key, val = self.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') # Check starting line number of # settings in makefiles section. line_num = val.contents['another'].line_number self.assertEqual(line_num, 12) line_num = val.contents['append'].line_number self.assertEqual(line_num, 20) def test_parse_empty_elem_strip_section(self): empty_elem_strip_should = OrderedDict([ ('a', 'a, b, c'), ('b', 'a, ,, d'), ('c', ',,,'), ('comment4', '')]) # Pop off the default, foo and makefiles section. self.sections.popitem(last=False) self.sections.popitem(last=False) self.sections.popitem(last=False) key, val = self.sections.popitem(last=False) self.assertTrue(isinstance(val, Section)) self.assertEqual(key, 'empty_elem_strip') is_dict = OrderedDict() for k in val: is_dict[k] = str(val[k]) self.assertEqual(is_dict, empty_elem_strip_should) # Check starting line number of # settings in empty_elem_strip section. line_num = val.contents['b'].line_number self.assertEqual(line_num, 24) def test_line_number_name_section(self): # Pop off the default, foo, makefiles and empty_elem_strip sections. self.sections.popitem(last=False) self.sections.popitem(last=False) self.sections.popitem(last=False) self.sections.popitem(last=False) key, val = self.sections.popitem(last=False) line_num = val.contents['key1'].line_number self.assertEqual(line_num, 30) def test_remove_empty_iter_elements(self): # Test with empty-elem stripping. uut = ConfParser(remove_empty_iter_elements=True) uut.parse(self.file) self.assertEqual(list(uut.get_section('EMPTY_ELEM_STRIP')['A']), ['a', 'b', 'c']) self.assertEqual(list(uut.get_section('EMPTY_ELEM_STRIP')['B']), ['a', 'd']) self.assertEqual(list(uut.get_section('EMPTY_ELEM_STRIP')['C']), []) # Test without stripping. uut = ConfParser(remove_empty_iter_elements=False) uut.parse(self.file) self.assertEqual(list(uut.get_section('EMPTY_ELEM_STRIP')['A']), ['a', 'b', 'c']) self.assertEqual(list(uut.get_section('EMPTY_ELEM_STRIP')['B']), ['a', '', '', 'd']) self.assertEqual(list(uut.get_section('EMPTY_ELEM_STRIP')['C']), ['', '', '', '']) def test_config_directory(self): self.uut.parse(self.tempdir) def test_settings_override_warning(self): self.assertEqual(self.cm.output[1], 'WARNING:root:test setting has ' 'already been defined in section ' 'foo. The previous setting will ' 'be overridden.') self.assertEqual(self.cm.output[2], 'WARNING:root:key1 setting has ' 'already been defined in section ' 'name. The previous setting will ' 'be overridden.')
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 ConfParserTest(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() try: os.remove(self.nonexistentfile) except FileNotFoundError: 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(FileNotFoundError, self.uut.parse, self.nonexistentfile) sections = self.uut.parse(self.file) self.assertNotEqual(self.uut.parse(self.file, True), 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)
def load(cls, language: str, docstyle: str, coalang_dir=None): """ Loads a ``DocstyleDefinition`` from the coala docstyle definition files. This function considers all settings inside the according coalang-files as markers, except ``param_start``, ``param_end`` and ``return_sep`` which are considered as special metadata markers. .. note:: When placing new coala docstyle definition files, these must consist of only lowercase letters and end with ``.coalang``! :param language: The case insensitive programming language of the documentation comment as a string. :param docstyle: The case insensitive documentation style/tool used to document code, e.g. ``"default"`` or ``"doxygen"``. :param coalang_dir: Path to directory with coalang docstyle definition files. This replaces the default path if given. :raises FileNotFoundError: Raised when the given docstyle was not found. :raises KeyError: Raised when the given language is not defined for given docstyle. :return: The ``DocstyleDefinition`` for given language and docstyle. """ docstyle = docstyle.lower() language_config_parser = ConfParser(remove_empty_iter_elements=False) coalang_file = os.path.join(coalang_dir or os.path.dirname(__file__), docstyle + '.coalang') try: docstyle_settings = language_config_parser.parse(coalang_file) except FileNotFoundError: raise FileNotFoundError('Docstyle definition ' + repr(docstyle) + ' not found.') language = language.lower() try: docstyle_settings = docstyle_settings[language] except KeyError: raise KeyError( 'Language {!r} is not defined for docstyle {!r}.'.format( language, docstyle)) metadata_settings = ('param_start', 'param_end', 'exception_start', 'exception_end', 'return_sep') metadata = cls.Metadata(*(str(docstyle_settings.get(req_setting, '')) for req_setting in metadata_settings)) marker_sets = ( tuple(value) for key, value in docstyle_settings.contents.items() if key not in metadata_settings and not key.startswith('comment')) return cls(language, docstyle, marker_sets, metadata)
def test_remove_empty_iter_elements(self): # Test with empty-elem stripping. uut = ConfParser(remove_empty_iter_elements=True) uut.parse(self.file) self.assertEqual(list(uut.get_section('EMPTY_ELEM_STRIP')['A']), ['a', 'b', 'c']) self.assertEqual(list(uut.get_section('EMPTY_ELEM_STRIP')['B']), ['a', 'd']) self.assertEqual(list(uut.get_section('EMPTY_ELEM_STRIP')['C']), []) # Test without stripping. uut = ConfParser(remove_empty_iter_elements=False) uut.parse(self.file) self.assertEqual(list(uut.get_section('EMPTY_ELEM_STRIP')['A']), ['a', 'b', 'c']) self.assertEqual(list(uut.get_section('EMPTY_ELEM_STRIP')['B']), ['a', '', '', 'd']) self.assertEqual(list(uut.get_section('EMPTY_ELEM_STRIP')['C']), ['', '', '', ''])
class ConfParserTest(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.parse(self.file, True), 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 ConfParserTest(unittest.TestCase): example_file = """to be ignored a_default, another = val TEST = tobeignored # do you know that thats a comment test = push t = escaped_\\=equal = escaped_\\#hash escaped_\\\\backslash = escaped_\\ space escaped_\\,comma = escaped_\\.dot [MakeFiles] j , another = a multiline value # just a omment # just a omment nokey. = value default.test = content makefiles.lastone = val [EMPTY_ELEM_STRIP] A = a, b, c B = a, ,, d C = ,,, """ 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 file: file.write(self.example_file) self.uut = ConfParser() try: os.remove(self.nonexistentfile) except FileNotFoundError: pass self.sections = self.uut.parse(self.file) def tearDown(self): os.remove(self.file) def test_parse_nonexisting_file(self): self.assertRaises(FileNotFoundError, self.uut.parse, self.nonexistentfile) self.assertNotEqual(self.uut.parse(self.file, True), self.sections) def test_parse_nonexisting_section(self): self.assertRaises(IndexError, self.uut.get_section, 'inexistent section') def test_parse_default_section(self): default_should = OrderedDict([ ('a_default', 'val'), ('another', 'val'), ('comment0', '# do you know that thats a comment'), ('test', 'content'), ('t', ''), ('escaped_=equal', 'escaped_#hash'), ('escaped_\\backslash', 'escaped_ space'), ('escaped_,comma', 'escaped_.dot')]) key, val = self.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) def test_parse_makefiles_section(self): 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', ''), ('escaped_=equal', 'escaped_#hash'), ('escaped_\\backslash', 'escaped_ space'), ('escaped_,comma', 'escaped_.dot')]) # Pop off the default section. self.sections.popitem(last=False) key, val = self.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') def test_parse_empty_elem_strip_section(self): empty_elem_strip_should = OrderedDict([ ('a', 'a, b, c'), ('b', 'a, ,, d'), ('c', ',,,'), ('comment4', ''), ('a_default', 'val'), ('another', 'val'), ('comment0', '# do you know that thats a comment'), ('test', 'content'), ('t', ''), ('escaped_=equal', 'escaped_#hash'), ('escaped_\\backslash', 'escaped_ space'), ('escaped_,comma', 'escaped_.dot')]) # Pop off the default and makefiles section. self.sections.popitem(last=False) self.sections.popitem(last=False) key, val = self.sections.popitem(last=False) self.assertTrue(isinstance(val, Section)) self.assertEqual(key, 'empty_elem_strip') is_dict = OrderedDict() for k in val: is_dict[k] = str(val[k]) self.assertEqual(is_dict, empty_elem_strip_should) def test_remove_empty_iter_elements(self): # Test with empty-elem stripping. uut = ConfParser(remove_empty_iter_elements=True) uut.parse(self.file) self.assertEqual(list(uut.get_section('EMPTY_ELEM_STRIP')['A']), ['a', 'b', 'c']) self.assertEqual(list(uut.get_section('EMPTY_ELEM_STRIP')['B']), ['a', 'd']) self.assertEqual(list(uut.get_section('EMPTY_ELEM_STRIP')['C']), []) # Test without stripping. uut = ConfParser(remove_empty_iter_elements=False) uut.parse(self.file) self.assertEqual(list(uut.get_section('EMPTY_ELEM_STRIP')['A']), ['a', 'b', 'c']) self.assertEqual(list(uut.get_section('EMPTY_ELEM_STRIP')['B']), ['a', '', '', 'd']) self.assertEqual(list(uut.get_section('EMPTY_ELEM_STRIP')['C']), ['', '', '', '']) def test_config_directory(self): self.uut.parse(self.tempdir)
class ConfParserTest(unittest.TestCase): example_file = """setting = without_section [foo] to be ignored a_default, another = val TEST = tobeignored # do you know that thats a comment test = push t = escaped_\\=equal = escaped_\\#hash escaped_\\\\backslash = escaped_\\ space escaped_\\,comma = escaped_\\.dot [MakeFiles] j , another = a multiline value # just a omment # just a omment nokey. = value foo.test = content makefiles.lastone = val append += key [EMPTY_ELEM_STRIP] A = a, b, c B = a, ,, d C = ,,, [name] key1 = value1 key2 = value1 key1 = value2 """ 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 file: file.write(self.example_file) self.uut = ConfParser() try: os.remove(self.nonexistentfile) except FileNotFoundError: pass logger = logging.getLogger() isnotdir = mock.Mock(return_value=False) with self.assertLogs(logger, 'WARNING') as self.cm: with mock.patch('os.path.isdir', isnotdir): self.sections = self.uut.parse(self.file) def tearDown(self): os.remove(self.file) def test_parse_nonexisting_file(self): isdir = mock.Mock(return_value=True) isnotdir = mock.Mock(return_value=False) with mock.patch('os.path.isdir', isdir): self.assertRaises(FileNotFoundError, self.uut.parse, self.nonexistentfile) with mock.patch('os.path.isdir', isnotdir): self.assertRaises(FileNotFoundError, self.uut.parse, self.nonexistentfile) self.assertNotEqual(self.uut.parse(self.file, True), self.sections) def test_parse_nonexisting_section(self): self.assertRaises(IndexError, self.uut.get_section, 'inexistent section') def test_parse_default_section_deprecated(self): default_should = OrderedDict([('setting', 'without_section')]) key, val = self.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) self.assertRegex(self.cm.output[0], 'A setting does not have a section.') def test_parse_foo_section(self): foo_should = OrderedDict([('a_default', 'val'), ('another', 'val'), ('comment0', '# do you know that thats a comment'), ('test', 'content'), ('t', ''), ('escaped_=equal', 'escaped_#hash'), ('escaped_\\backslash', 'escaped_ space'), ('escaped_,comma', 'escaped_.dot')]) # Pop off the default section. self.sections.popitem(last=False) key, val = self.sections.popitem(last=False) self.assertTrue(isinstance(val, Section)) self.assertEqual(key, 'foo') is_dict = OrderedDict() for k in val: is_dict[k] = str(val[k]) self.assertEqual(is_dict, foo_should) def test_parse_makefiles_section(self): makefiles_should = OrderedDict([('j', 'a\nmultiline\nvalue'), ('another', 'a\nmultiline\nvalue'), ('comment1', '# just a omment'), ('comment2', '# just a omment'), ('lastone', 'val'), ('append', 'key'), ('comment3', '')]) # Pop off the default and foo section. self.sections.popitem(last=False) self.sections.popitem(last=False) key, val = self.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') def test_parse_empty_elem_strip_section(self): empty_elem_strip_should = OrderedDict([('a', 'a, b, c'), ('b', 'a, ,, d'), ('c', ',,,'), ('comment4', '')]) # Pop off the default, foo and makefiles section. self.sections.popitem(last=False) self.sections.popitem(last=False) self.sections.popitem(last=False) key, val = self.sections.popitem(last=False) self.assertTrue(isinstance(val, Section)) self.assertEqual(key, 'empty_elem_strip') is_dict = OrderedDict() for k in val: is_dict[k] = str(val[k]) self.assertEqual(is_dict, empty_elem_strip_should) def test_remove_empty_iter_elements(self): # Test with empty-elem stripping. uut = ConfParser(remove_empty_iter_elements=True) isnotdir = mock.Mock(return_value=False) with mock.patch('os.path.isdir', isnotdir): uut.parse(self.file) self.assertEqual(list(uut.get_section('EMPTY_ELEM_STRIP')['A']), ['a', 'b', 'c']) self.assertEqual(list(uut.get_section('EMPTY_ELEM_STRIP')['B']), ['a', 'd']) self.assertEqual(list(uut.get_section('EMPTY_ELEM_STRIP')['C']), []) # Test without stripping. uut = ConfParser(remove_empty_iter_elements=False) with mock.patch('os.path.isdir', isnotdir): uut.parse(self.file) self.assertEqual(list(uut.get_section('EMPTY_ELEM_STRIP')['A']), ['a', 'b', 'c']) self.assertEqual(list(uut.get_section('EMPTY_ELEM_STRIP')['B']), ['a', '', '', 'd']) self.assertEqual(list(uut.get_section('EMPTY_ELEM_STRIP')['C']), ['', '', '', '']) def test_config_directory(self): self.uut.parse(self.tempdir) def test_settings_override_warning(self): self.assertEqual( self.cm.output[1], 'WARNING:root:test setting has ' 'already been defined in section ' 'foo. The previous setting will ' 'be overridden.') self.assertEqual( self.cm.output[2], 'WARNING:root:key1 setting has ' 'already been defined in section ' 'name. The previous setting will ' 'be overridden.')
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
def test_remove_empty_iter_elements(self): # Test with empty-elem stripping. uut = ConfParser(remove_empty_iter_elements=True) isnotdir = mock.Mock(return_value=False) with mock.patch('os.path.isdir', isnotdir): uut.parse(self.file) self.assertEqual(list(uut.get_section('EMPTY_ELEM_STRIP')['A']), ['a', 'b', 'c']) self.assertEqual(list(uut.get_section('EMPTY_ELEM_STRIP')['B']), ['a', 'd']) self.assertEqual(list(uut.get_section('EMPTY_ELEM_STRIP')['C']), []) # Test without stripping. uut = ConfParser(remove_empty_iter_elements=False) with mock.patch('os.path.isdir', isnotdir): uut.parse(self.file) self.assertEqual(list(uut.get_section('EMPTY_ELEM_STRIP')['A']), ['a', 'b', 'c']) self.assertEqual(list(uut.get_section('EMPTY_ELEM_STRIP')['B']), ['a', '', '', 'd']) self.assertEqual(list(uut.get_section('EMPTY_ELEM_STRIP')['C']), ['', '', '', ''])