diff --git a/bugwarrior/config/load.py b/bugwarrior/config/load.py index 97bcbc76..e7454c1d 100644 --- a/bugwarrior/config/load.py +++ b/bugwarrior/config/load.py @@ -120,7 +120,8 @@ def parse_file(configpath: str) -> dict: def load_config(main_section, interactive, quiet) -> Config: configpath = get_config_path() rawconfig = parse_file(configpath) - rawconfig['flavor'][main_section]['interactive'] = interactive + for flavor in rawconfig['flavor'].values(): + flavor['interactive'] = interactive config = validate_config(rawconfig, main_section, configpath) configure_logging( config.main.log_file, 'WARNING' if quiet else config.main.log_level diff --git a/bugwarrior/config/schema.py b/bugwarrior/config/schema.py index b92f6765..4f9f20f8 100644 --- a/bugwarrior/config/schema.py +++ b/bugwarrior/config/schema.py @@ -138,7 +138,7 @@ class MainSectionConfig(BaseConfig): # added during configuration loading #: Interactive status. - interactive: bool = False + interactive: bool @computed_field @property diff --git a/bugwarrior/config/validation.py b/bugwarrior/config/validation.py index dc8ea7f1..781121ea 100644 --- a/bugwarrior/config/validation.py +++ b/bugwarrior/config/validation.py @@ -189,7 +189,7 @@ def validate_config(config: dict, main_section: str, config_path: str) -> "Confi f"[{flavor_name}]\ntargets = {flavor.targets} <- No [{target}] section found\n" ) - main = flavors.get(main_section, MainSectionConfig(targets=[])) + main = flavors.get(main_section, MainSectionConfig(targets=[], interactive=False)) filtered_service_configs = [ service_config for service_config in service_configs diff --git a/tests/config/test_load.py b/tests/config/test_load.py index 986f3590..2e15c940 100644 --- a/tests/config/test_load.py +++ b/tests/config/test_load.py @@ -263,3 +263,31 @@ def test_ini_wrong_prefix(self): with self.assertRaises(SystemExit): load.parse_file(config_path) + + +class TestLoadConfig(LoadTest): + def setUp(self): + self.basedir = Path(__file__).parent + super().setUp() + + def test_main_section_does_not_exist(self): + config_path = self.create(".bugwarriorrc") + with open(config_path, 'w') as fout: + fout.write( + textwrap.dedent(""" + [redmine] + service = redmine + redmine.url = example.com + """) + ) + + with self.assertRaises(SystemExit): + load.load_config("general", False, False) + + self.assertEqual(len(self.caplog.records), 1) + self.assertIn("No section: 'general'", self.caplog.records[0].message) + + def test_interactive_flag_propagated(self): + os.environ['BUGWARRIORRC'] = str(self.basedir / 'example-bugwarriorrc') + config = load.load_config('general', interactive=True, quiet=False) + self.assertTrue(config.main.interactive) diff --git a/tests/config/test_validation.py b/tests/config/test_validation.py index 60820e2b..0c60a325 100644 --- a/tests/config/test_validation.py +++ b/tests/config/test_validation.py @@ -141,7 +141,9 @@ def test_deprecated_project_name(self): self.validate() def test_flavors(self): - self.config['flavor'] = {'myflavor': {'targets': ['my_service', 'my_gitlab']}} + self.config['flavor'] = { + 'myflavor': {'targets': ['my_service', 'my_gitlab'], 'interactive': False} + } self.validate() def test_quoted_flavor_key_error(self): @@ -175,6 +177,10 @@ def test_load_and_validate_example_files(self): for main_section, expected_configs in expected_by_flavor.items(): with self.subTest(config=config_path.name, main_section=main_section): formatted_config = parse_file(str(config_path)) + + for flavor in formatted_config['flavor'].values(): + flavor['interactive'] = False + config = validation.validate_config( formatted_config, main_section, str(config_path) )