Skip to content

Commit 33e2753

Browse files
Handle empty config files (#41)
* Handle empty config files Fixes: #40
1 parent 59d04d4 commit 33e2753

File tree

2 files changed

+84
-6
lines changed

2 files changed

+84
-6
lines changed

joft/utils.py

+34-6
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,19 @@ def load_and_parse_yaml_file(path: str) -> typing.Dict[str, typing.Any]:
1515
return yaml_obj
1616

1717

18+
def read_and_validate_config(
19+
path: str | pathlib.Path,
20+
) -> typing.Dict[str, typing.Any] | None:
21+
"""Read and return config file is it's valid. Return None otherwise."""
22+
with open(path, "rb") as fp:
23+
config = tomllib.load(fp)
24+
25+
config["jira"]["server"]["hostname"]
26+
config["jira"]["server"]["pat_token"]
27+
28+
return config
29+
30+
1831
def load_toml_app_config() -> typing.Any:
1932
possible_paths = []
2033

@@ -26,7 +39,27 @@ def load_toml_app_config() -> typing.Any:
2639
for path in possible_paths:
2740
config_file_path = pathlib.Path(path) / "joft.config.toml"
2841
if config_file_path.is_file():
29-
break
42+
try:
43+
config = read_and_validate_config(config_file_path)
44+
except Exception as e:
45+
err_msg = textwrap.dedent(f"""\
46+
[ERROR] Configuration file {config_file_path} is invalid:
47+
48+
{type(e).__name__} - {str(e)}
49+
50+
Configuration file should have the following content:
51+
52+
[jira.server]
53+
hostname = "<your jira server url>"
54+
pat_token = "<your jira pat token>"
55+
56+
and should be stored in one of the following directories:
57+
{', '.join(possible_paths)}\
58+
""")
59+
print(err_msg)
60+
sys.exit(1)
61+
else:
62+
return config
3063
else:
3164
err_msg = textwrap.dedent(f"""\
3265
[ERROR] Cannot find configuration file 'joft.config.toml'.
@@ -43,8 +76,3 @@ def load_toml_app_config() -> typing.Any:
4376

4477
print(err_msg)
4578
sys.exit(1)
46-
47-
with open(config_file_path, "rb") as fp:
48-
config = tomllib.load(fp)
49-
50-
return config

tests/test_utils.py

+50
Original file line numberDiff line numberDiff line change
@@ -81,3 +81,53 @@ def test_load_toml_app_config_no_config_found(mock_platformdirs, mock_cwd) -> No
8181

8282
assert "Cannot find configuration file" in mock_stdout.getvalue()
8383
assert sys_exit.value.args[0] == 1
84+
85+
86+
@unittest.mock.patch("joft.utils.pathlib.Path.cwd")
87+
def test_load_toml_app_config_invalid_config_found(mock_cwd) -> None:
88+
"""
89+
Test that we will end with a non-zero error code when there is an invalid
90+
config present and printing a message on the stdout.
91+
"""
92+
93+
invalid_config_file_contents = """[jira.server]
94+
pat_token = "__pat_token__"
95+
"""
96+
97+
with tempfile.TemporaryDirectory() as tmpdir:
98+
mock_cwd.return_value = tmpdir
99+
100+
config_file_path = os.path.join(tmpdir, "joft.config.toml")
101+
with open(config_file_path, "w") as fp:
102+
fp.write(invalid_config_file_contents)
103+
104+
with unittest.mock.patch("sys.stdout", new=io.StringIO()) as mock_stdout:
105+
with pytest.raises(SystemExit) as sys_exit:
106+
joft.utils.load_toml_app_config()
107+
108+
assert f"Configuration file {config_file_path} is invalid" in mock_stdout.getvalue()
109+
assert "KeyError - 'hostname'" in mock_stdout.getvalue()
110+
assert sys_exit.value.args[0] == 1
111+
112+
113+
@pytest.mark.parametrize(
114+
"config_file_content, raises",
115+
[
116+
("[jira.server]\nhostname = 'foo'\npat_token = 'bar'", None),
117+
("", KeyError),
118+
("[jira.server]\nhostname = 'foo'", KeyError),
119+
("[jira.server]\npat_token = 'bar'", KeyError),
120+
("hostname = 'foo'\npat_token = 'bar'", KeyError),
121+
],
122+
)
123+
def test_read_and_validate_config(config_file_content, raises, tmp_path) -> None:
124+
config_file_path = tmp_path / "joft.config.toml"
125+
config_file_path.write_text(config_file_content)
126+
127+
if raises is None:
128+
config = joft.utils.read_and_validate_config(config_file_path)
129+
assert config["jira"]["server"]["hostname"] == "foo"
130+
assert config["jira"]["server"]["pat_token"] == "bar"
131+
else:
132+
with pytest.raises(raises):
133+
config = joft.utils.read_and_validate_config(config_file_path)

0 commit comments

Comments
 (0)