# pylint: disable=redefined-outer-name,missing-function-docstring,protected-access,global-statement # pylint: disable=global-variable-not-assigned """ Tests on config lib """ import logging import os import configparser import pytest from mylib.config import Config, ConfigSection from mylib.config import BooleanOption from mylib.config import StringOption runned = {} 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 runned runned['test_add_section_with_callback'] = False def test_callback(loaded_config): global runned assert loaded_config == config assert runned['test_add_section_with_callback'] is False runned['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 runned['test_add_section_with_callback'] is False config.parse_arguments_options(argv=[], create=False) assert runned['test_add_section_with_callback'] is True assert test_callback in config._loaded_callbacks_executed # Try to execute again to verify callback is not runned 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 runned runned['test_add_section_with_callback_already_loaded'] = False def test_callback(loaded_config): global runned assert loaded_config == config assert runned['test_add_section_with_callback_already_loaded'] is False runned['test_add_section_with_callback_already_loaded'] = True section = config.add_section(name, loaded_callback=test_callback) assert isinstance(section, ConfigSection) assert runned['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 runned 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 = dict( 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} = """