Skip to content

Commit 3b10984

Browse files
committed
Fail gracefully if config lacks the mandatory main section
Currently, if a user didn't put `[general]` section in config file, bugwarrior fails like this: Traceback (most recent call last): File "/usr/bin/bugwarrior", line 8, in <module> sys.exit(cli()) ~~~^^ File "/usr/lib/python3.14/site-packages/click/core.py", line 1485, in __call__ return self.main(*args, **kwargs) ~~~~~~~~~^^^^^^^^^^^^^^^^^ File "/usr/lib/python3.14/site-packages/click/core.py", line 1406, in main rv = self.invoke(ctx) File "/usr/lib/python3.14/site-packages/click/core.py", line 1873, in invoke return _process_result(sub_ctx.command.invoke(sub_ctx)) ~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^ File "/usr/lib/python3.14/site-packages/click/core.py", line 1269, in invoke return ctx.invoke(self.callback, **ctx.params) ~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3.14/site-packages/click/core.py", line 824, in invoke return callback(*args, **kwargs) File "/usr/lib/python3.14/site-packages/click/decorators.py", line 34, in new_func return f(get_current_context(), *args, **kwargs) File "/usr/lib/python3.14/site-packages/bugwarrior/command.py", line 62, in wrapped_subcommand_callback return ctx.invoke(subcommand_callback, *args, **kwargs) ~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3.14/site-packages/click/core.py", line 824, in invoke return callback(*args, **kwargs) File "/usr/lib/python3.14/site-packages/bugwarrior/command.py", line 105, in pull config = _try_load_config(main_section, interactive, quiet) File "/usr/lib/python3.14/site-packages/bugwarrior/command.py", line 35, in _try_load_config return load_config(main_section, interactive, quiet) File "/usr/lib/python3.14/site-packages/bugwarrior/config/load.py", line 122, in load_config rawconfig['flavor'][main_section]['interactive'] = interactive ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^ KeyError: 'general' This is confusing — it looks more like bugwarrior broke due to some API change in Python, rather than because of a user mistake. So handle this case with explicit check. Now it will fail instead like this: CRITICAL:bugwarrior.command:Could not load configuration. Maybe you have not created a configuration file. bugwarrior.config.load.ErrConfigLacksSection: Configuration lacks section "general"
1 parent 5bca612 commit 3b10984

File tree

3 files changed

+19
-3
lines changed

3 files changed

+19
-3
lines changed

bugwarrior/command.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,12 @@
1010
from lockfile.pidlockfile import PIDLockFile
1111

1212
from bugwarrior.collect import aggregate_issues, get_service
13-
from bugwarrior.config import get_config_path, get_keyring, load_config
13+
from bugwarrior.config import (
14+
ErrConfigLacksSection,
15+
get_config_path,
16+
get_keyring,
17+
load_config,
18+
)
1419
from bugwarrior.db import get_defined_udas_as_strings, synchronize
1520

1621
if TYPE_CHECKING:
@@ -33,7 +38,7 @@ def _try_load_config(
3338
) -> "Config":
3439
try:
3540
return load_config(main_section, interactive, quiet)
36-
except OSError:
41+
except (ErrConfigLacksSection, OSError):
3742
# Our standard logging configuration depends on the bugwarrior
3843
# configuration file which just failed to load.
3944
logging.basicConfig()

bugwarrior/config/__init__.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,12 @@
44
"""
55

66
from .data import BugwarriorData
7-
from .load import BUGWARRIORRC, get_config_path, load_config # noqa: F401
7+
from .load import ( # noqa: F401
8+
BUGWARRIORRC,
9+
ErrConfigLacksSection,
10+
get_config_path,
11+
load_config,
12+
)
813
from .schema import (
914
ConfigList, # noqa: F401
1015
ExpandedPath, # noqa: F401

bugwarrior/config/load.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,15 @@ def parse_file(configpath: str) -> dict:
116116
return format_config(config)
117117

118118

119+
class ErrConfigLacksSection(Exception):
120+
"""Raised if config lacks a section"""
121+
122+
119123
def load_config(main_section, interactive, quiet) -> Config:
120124
configpath = get_config_path()
121125
rawconfig = parse_file(configpath)
126+
if main_section not in rawconfig['flavor']:
127+
raise ErrConfigLacksSection(f'Configuration lacks section "{main_section}"')
122128
rawconfig['flavor'][main_section]['interactive'] = interactive
123129
config = validate_config(rawconfig, main_section, configpath)
124130
configure_logging(

0 commit comments

Comments
 (0)