diff --git a/test/test_configuration.py b/test/test_configuration.py index 8eb6296..d6b19bb 100644 --- a/test/test_configuration.py +++ b/test/test_configuration.py @@ -63,6 +63,16 @@ class TestEnv: assert env["task_rc"] == Path("/a/dir/that/dont/exist/file") assert env["task_data"] == Path("~/somewhere/tasks") + def test_env_parses_boolean_true(self, isolate_env, monkeypatch): + monkeypatch.setenv("TOPEN_NOTES_QUIET", "true") + env = parse_env() + assert env["notes_quiet"] is True + + def test_env_parses_boolean_false(self, isolate_env, monkeypatch): + monkeypatch.setenv("TOPEN_NOTES_QUIET", "false") + env = parse_env() + assert env["notes_quiet"] is False + @pytest.fixture def fake_rc(tmp_path: Path, monkeypatch): @@ -89,6 +99,20 @@ class TestRcFile: assert rc_cfg["notes_editor"] == "micro" assert rc_cfg["notes_quiet"] is True + def test_taskrc_parses_boolean_true(self, fake_rc): + fake_rc.write_text(""" + notes.quiet=true + """) + rc_cfg = parse_rc(fake_rc) + assert rc_cfg["notes_quiet"] is True + + def test_taskrc_parses_boolean_false(self, fake_rc): + fake_rc.write_text(""" + notes.quiet=false + """) + rc_cfg = parse_rc(fake_rc) + assert rc_cfg["notes_quiet"] is False + class TestTConf: def test_paths_are_expanded(self): diff --git a/topen.py b/topen.py index a4c32a4..0143907 100755 --- a/topen.py +++ b/topen.py @@ -23,7 +23,7 @@ import subprocess import sys from dataclasses import asdict, dataclass from pathlib import Path -from typing import Any, Self, cast +from typing import Any, Callable, Self, cast from tasklib import Task, TaskWarrior @@ -130,8 +130,9 @@ class Opt: rc: str | None default: Any = None metavar: str | None = None - cast: type = str + cast: type | Callable = str help_text: str = "" + flag: bool = False def _real_path(p: Path | str) -> Path: @@ -146,6 +147,24 @@ def _determine_default_task_rc() -> Path: return _real_path("~/.config/task/taskrc") +def _strtobool(val: str) -> bool: + """Convert a string representation of truth. + + Coverts either to True or False, raising an error if it does not find a + valid value. + True values are 'y', 'yes', 't', 'true', 'on', and '1'; false values are 'n', + 'no', 'f', 'false', 'off', and '0'. + Raises ValueError if 'val' is anything else. + """ + val = val.lower() + if val in ("y", "yes", "t", "true", "on", "1"): + return True + elif val in ("n", "no", "f", "false", "off", "0"): + return False + else: + raise ValueError(f"Invalid boolean value {val}") + + OPTIONS: dict[str, Opt] = { "task_id": Opt(None, None, None, default=None), "task_rc": Opt( @@ -204,7 +223,7 @@ OPTIONS: dict[str, Opt] = { "TOPEN_NOTES_QUIET", "notes.quiet", default=False, - cast=bool, + cast=_strtobool, help_text="Silence any verbose displayed information", ), }