# pylint: disable=redefined-outer-name,missing-function-docstring,protected-access,global-statement # pylint: disable=global-variable-not-assigned """ Tests on config lib """ import configparser import logging import os import pytest from mylib.config import BooleanOption, Config, ConfigSection, StringOption tested = {} def test_config_init_default_args(): appname = "Test app" config = Config(appname) assert config.appname == appname assert config.version == "0.0" assert config.encoding == "utf-8" def test_config_init_custom_args(): appname = "Test app" version = "1.43" encoding = "ISO-8859-1" config = Config(appname, version=version, encoding=encoding) assert config.appname == appname assert config.version == version assert config.encoding == encoding def test_add_section_default_args(): config = Config("Test app") name = "test_section" section = config.add_section(name) assert isinstance(section, ConfigSection) assert config.sections[name] == section assert section.name == name assert section.comment is None assert section.order == 10 def test_add_section_custom_args(): config = Config("Test app") name = "test_section" comment = "Test" order = 20 section = config.add_section(name, comment=comment, order=order) assert isinstance(section, ConfigSection) assert section.name == name assert section.comment == comment assert section.order == order def test_add_section_with_callback(): config = Config("Test app") name = "test_section" global tested tested["test_add_section_with_callback"] = False def test_callback(loaded_config): global tested assert loaded_config == config assert tested["test_add_section_with_callback"] is False tested["test_add_section_with_callback"] = True section = config.add_section(name, loaded_callback=test_callback) assert isinstance(section, ConfigSection) assert test_callback in config._loaded_callbacks assert tested["test_add_section_with_callback"] is False config.parse_arguments_options(argv=[], create=False) assert tested["test_add_section_with_callback"] is True assert test_callback in config._loaded_callbacks_executed # Try to execute again to verify callback is not tested again config._loaded() def test_add_section_with_callback_already_loaded(): config = Config("Test app") name = "test_section" config.parse_arguments_options(argv=[], create=False) global tested tested["test_add_section_with_callback_already_loaded"] = False def test_callback(loaded_config): global tested assert loaded_config == config assert tested["test_add_section_with_callback_already_loaded"] is False tested["test_add_section_with_callback_already_loaded"] = True section = config.add_section(name, loaded_callback=test_callback) assert isinstance(section, ConfigSection) assert tested["test_add_section_with_callback_already_loaded"] is True assert test_callback in config._loaded_callbacks assert test_callback in config._loaded_callbacks_executed # Try to execute again to verify callback is not tested again config._loaded() def test_add_option_default_args(): config = Config("Test app") section = config.add_section("my_section") assert isinstance(section, ConfigSection) name = "my_option" option = section.add_option(StringOption, name) assert isinstance(option, StringOption) assert name in section.options and section.options[name] == option assert option.config == config assert option.section == section assert option.name == name assert option.default is None assert option.comment is None assert option.no_arg is False assert option.arg is None assert option.short_arg is None assert option.arg_help is None def test_add_option_custom_args(): config = Config("Test app") section = config.add_section("my_section") assert isinstance(section, ConfigSection) name = "my_option" kwargs = { "default": "default value", "comment": "my comment", "no_arg": True, "arg": "--my-option", "short_arg": "-M", "arg_help": "My help", } option = section.add_option(StringOption, name, **kwargs) assert isinstance(option, StringOption) assert name in section.options and section.options[name] == option assert option.config == config assert option.section == section assert option.name == name for arg, value in kwargs.items(): assert getattr(option, arg) == value def test_defined(): config = Config("Test app") section_name = "my_section" opt_name = "my_option" assert not config.defined(section_name, opt_name) section = config.add_section("my_section") assert isinstance(section, ConfigSection) section.add_option(StringOption, opt_name) assert config.defined(section_name, opt_name) def test_isset(): config = Config("Test app") section_name = "my_section" opt_name = "my_option" assert not config.isset(section_name, opt_name) section = config.add_section("my_section") assert isinstance(section, ConfigSection) option = section.add_option(StringOption, opt_name) assert not config.isset(section_name, opt_name) config.parse_arguments_options(argv=[option.parser_argument_name, "value"], create=False) assert config.isset(section_name, opt_name) def test_not_isset(): config = Config("Test app") section_name = "my_section" opt_name = "my_option" assert not config.isset(section_name, opt_name) section = config.add_section("my_section") assert isinstance(section, ConfigSection) section.add_option(StringOption, opt_name) assert not config.isset(section_name, opt_name) config.parse_arguments_options(argv=[], create=False) assert not config.isset(section_name, opt_name) def test_get(): config = Config("Test app") section_name = "my_section" opt_name = "my_option" opt_value = "value" section = config.add_section("my_section") option = section.add_option(StringOption, opt_name) config.parse_arguments_options(argv=[option.parser_argument_name, opt_value], create=False) assert config.get(section_name, opt_name) == opt_value def test_get_default(): config = Config("Test app") section_name = "my_section" opt_name = "my_option" opt_default_value = "value" section = config.add_section("my_section") section.add_option(StringOption, opt_name, default=opt_default_value) config.parse_arguments_options(argv=[], create=False) assert config.get(section_name, opt_name) == opt_default_value def test_logging_splited_stdout_stderr(capsys): config = Config("Test app") config.parse_arguments_options(argv=["-C", "-v"], create=False) info_msg = "[info]" err_msg = "[error]" logging.getLogger().info(info_msg) logging.getLogger().error(err_msg) captured = capsys.readouterr() assert info_msg in captured.out assert info_msg not in captured.err assert err_msg in captured.err assert err_msg not in captured.out # # Test option types # @pytest.fixture() def config_with_file(tmpdir): config = Config("Test app") config_dir = tmpdir.mkdir("config") config_file = config_dir.join("config.ini") config.save(os.path.join(config_file.dirname, config_file.basename)) return config def generate_mock_input(expected_prompt, input_value): def mock_input(self, prompt): # pylint: disable=unused-argument assert prompt == expected_prompt return input_value return mock_input # Boolean option def test_boolean_option_from_config(config_with_file): section = config_with_file.add_section("test") default = True option = section.add_option(BooleanOption, "test_bool", default=default) config_with_file.save() option.set(not default) assert option._from_config is not default option.set(default) assert not option._isset_in_config_file with pytest.raises(configparser.NoOptionError): assert option._from_config is default def test_boolean_option_ask_value(mocker): config = Config("Test app") section = config.add_section("test") name = "test_bool" option = section.add_option(BooleanOption, name, default=True) mocker.patch( "mylib.config.BooleanOption._get_user_input", generate_mock_input(f"{name}: [Y/n] ", "y") ) assert option.ask_value(set_it=False) is True mocker.patch( "mylib.config.BooleanOption._get_user_input", generate_mock_input(f"{name}: [Y/n] ", "Y") ) assert option.ask_value(set_it=False) is True mocker.patch( "mylib.config.BooleanOption._get_user_input", generate_mock_input(f"{name}: [Y/n] ", "") ) assert option.ask_value(set_it=False) is True mocker.patch( "mylib.config.BooleanOption._get_user_input", generate_mock_input(f"{name}: [Y/n] ", "n") ) assert option.ask_value(set_it=False) is False mocker.patch( "mylib.config.BooleanOption._get_user_input", generate_mock_input(f"{name}: [Y/n] ", "N") ) assert option.ask_value(set_it=False) is False def test_boolean_option_to_config(): config = Config("Test app") section = config.add_section("test") default = True option = section.add_option(BooleanOption, "test_bool", default=default) assert option.to_config(True) == "true" assert option.to_config(False) == "false" def test_boolean_option_export_to_config(config_with_file): section = config_with_file.add_section("test") name = "test_bool" comment = "Test boolean" default = True option = section.add_option(BooleanOption, name, default=default, comment=comment) assert ( option.export_to_config() == f"""# {comment} # Default: {str(default).lower()} # {name} = """ ) option.set(not default) assert ( option.export_to_config() == f"""# {comment} # Default: {str(default).lower()} {name} = {str(not default).lower()} """ ) option.set(default) assert ( option.export_to_config() == f"""# {comment} # Default: {str(default).lower()} # {name} = """ )