Compare commits

..

No commits in common. "e960f56b9347d4257942af0a745aff52150c1e10" and "13c34b08e27b13af631fbf3fb0024288669eb22d" have entirely different histories.

2 changed files with 15 additions and 39 deletions

View file

@ -1,17 +0,0 @@
from pathlib import Path
from unittest.mock import Mock, patch
from topen import add_annotation, open_editor
def test_open_editor_escapes_shell():
"""Ensure filenames with spaces/metas do not allow shell injection."""
with patch("subprocess.run") as run_mock:
open_editor(Path("my note$1.txt"), "vim")
run_mock.assert_called_once_with(["vim", "my note$1.txt"], check=True)
def test_add_annotation_calls_tasklib():
task = Mock()
add_annotation(task, "hello")
task.add_annotation.assert_called_once_with("hello")

View file

@ -63,9 +63,11 @@ def main(cfg: "TConf | None" = None, io: "_IO | None" = None) -> int:
fpath = get_notes_file(uuid, notes_dir=cfg.notes_dir, notes_ext=cfg.notes_ext)
_ensure_parent_dir(fpath)
if not fpath.parent.exists():
fpath.parent.mkdir(parents=True, exist_ok=True)
io.out(f"Editing note: {fpath}")
open_editor(fpath, editor=cfg.notes_editor, io=io)
open_editor(fpath, editor=cfg.notes_editor)
if fpath.exists():
if is_annotation_missing(task, annotation_content=cfg.notes_annot):
@ -95,13 +97,9 @@ def get_notes_file(uuid: str, notes_dir: Path, notes_ext: str) -> Path:
return Path(notes_dir).joinpath(f"{uuid}.{notes_ext}")
def open_editor(file: Path, editor: str, io: "_IO | None" = None) -> None:
def open_editor(file: Path, editor: str) -> None:
"""Opens a file with the chosen editor."""
try:
_ = subprocess.run([editor, str(file)], check=True)
except subprocess.CalledProcessError:
if io:
io.err("Editor exited with an error, aborting.\n")
_ = subprocess.run(f"{editor} {file}", shell=True)
def is_annotation_missing(task: Task, annotation_content: str) -> bool:
@ -137,21 +135,16 @@ class Opt:
is_flag: bool = False
def _expand_path(p: Path | str) -> Path:
def _real_path(p: Path | str) -> Path:
return Path(os.path.expandvars(p)).expanduser()
def _ensure_parent_dir(file: Path) -> None:
if not file.parent.exists():
file.parent.mkdir(parents=True, exist_ok=True)
def _determine_default_task_rc() -> Path:
if _expand_path("~/.taskrc").exists():
return _expand_path("~/.taskrc")
if _expand_path("$XDG_CONFIG_HOME/task/taskrc").exists():
return _expand_path("$XDG_CONFIG_HOME/task/taskrc")
return _expand_path("~/.config/task/taskrc")
if _real_path("~/.taskrc").exists():
return _real_path("~/.taskrc")
if _real_path("$XDG_CONFIG_HOME/task/taskrc").exists():
return _real_path("$XDG_CONFIG_HOME/task/taskrc")
return _real_path("~/.config/task/taskrc")
def _strtobool(val: str) -> bool:
@ -265,11 +258,11 @@ class TConf:
"""If set topen will give no feedback on note editing."""
def __post_init__(self):
self.task_rc = _expand_path(self.task_rc)
self.task_data = _expand_path(self.task_data)
self.task_rc = _real_path(self.task_rc)
self.task_data = _real_path(self.task_data)
if self.notes_dir == NON_EXISTENT_PATH:
self.notes_dir = self._default_notes_dir()
self.notes_dir = _expand_path(self.notes_dir)
self.notes_dir = _real_path(self.notes_dir)
if not self.notes_editor:
self.notes_editor = (
os.getenv("EDITOR")