worklog-opsdevnz 0.2.0__tar.gz → 0.2.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (23) hide show
  1. {worklog_opsdevnz-0.2.0/src/worklog_opsdevnz.egg-info → worklog_opsdevnz-0.2.1}/PKG-INFO +5 -1
  2. {worklog_opsdevnz-0.2.0 → worklog_opsdevnz-0.2.1}/README.md +4 -0
  3. {worklog_opsdevnz-0.2.0 → worklog_opsdevnz-0.2.1}/pyproject.toml +6 -1
  4. {worklog_opsdevnz-0.2.0 → worklog_opsdevnz-0.2.1}/src/worklog_opsdevnz/cli.py +19 -3
  5. worklog_opsdevnz-0.2.1/src/worklog_opsdevnz/paths.py +73 -0
  6. {worklog_opsdevnz-0.2.0 → worklog_opsdevnz-0.2.1/src/worklog_opsdevnz.egg-info}/PKG-INFO +5 -1
  7. worklog_opsdevnz-0.2.1/tests/test_cli.py +137 -0
  8. worklog_opsdevnz-0.2.1/tests/test_paths.py +79 -0
  9. worklog_opsdevnz-0.2.0/src/worklog_opsdevnz/paths.py +0 -28
  10. worklog_opsdevnz-0.2.0/tests/test_cli.py +0 -71
  11. worklog_opsdevnz-0.2.0/tests/test_paths.py +0 -29
  12. {worklog_opsdevnz-0.2.0 → worklog_opsdevnz-0.2.1}/LICENSE +0 -0
  13. {worklog_opsdevnz-0.2.0 → worklog_opsdevnz-0.2.1}/setup.cfg +0 -0
  14. {worklog_opsdevnz-0.2.0 → worklog_opsdevnz-0.2.1}/src/worklog_opsdevnz/__init__.py +0 -0
  15. {worklog_opsdevnz-0.2.0 → worklog_opsdevnz-0.2.1}/src/worklog_opsdevnz/config.py +0 -0
  16. {worklog_opsdevnz-0.2.0 → worklog_opsdevnz-0.2.1}/src/worklog_opsdevnz/template.py +0 -0
  17. {worklog_opsdevnz-0.2.0 → worklog_opsdevnz-0.2.1}/src/worklog_opsdevnz.egg-info/SOURCES.txt +0 -0
  18. {worklog_opsdevnz-0.2.0 → worklog_opsdevnz-0.2.1}/src/worklog_opsdevnz.egg-info/dependency_links.txt +0 -0
  19. {worklog_opsdevnz-0.2.0 → worklog_opsdevnz-0.2.1}/src/worklog_opsdevnz.egg-info/entry_points.txt +0 -0
  20. {worklog_opsdevnz-0.2.0 → worklog_opsdevnz-0.2.1}/src/worklog_opsdevnz.egg-info/requires.txt +0 -0
  21. {worklog_opsdevnz-0.2.0 → worklog_opsdevnz-0.2.1}/src/worklog_opsdevnz.egg-info/top_level.txt +0 -0
  22. {worklog_opsdevnz-0.2.0 → worklog_opsdevnz-0.2.1}/tests/test_config.py +0 -0
  23. {worklog_opsdevnz-0.2.0 → worklog_opsdevnz-0.2.1}/tests/test_template.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: worklog-opsdevnz
3
- Version: 0.2.0
3
+ Version: 0.2.1
4
4
  Summary: Configurable worklog management CLI for dated development logs
5
5
  Author-email: "OpsDev.nz Collective" <john@opsdev.nz>
6
6
  License: Apache-2.0
@@ -50,6 +50,9 @@ worklog-opsdevnz --version
50
50
 
51
51
  # Override the editor for this run
52
52
  worklog-opsdevnz --editor nvim
53
+
54
+ # Open the most recent previous entry
55
+ worklog-opsdevnz -p
53
56
  ```
54
57
 
55
58
  ## Configuration
@@ -85,6 +88,7 @@ title = "Next"
85
88
  - Configurable section headers per project
86
89
  - Custom body templates with `{{DATE}}` and `{{TITLE}}` placeholders
87
90
  - Editor integration: `-e` flag → config → `$VISUAL` → `$EDITOR`
91
+ - `-p` / `--previous` flag to open the most recent past entry
88
92
  - `--version` flag for installed version
89
93
 
90
94
  ## Requirements
@@ -16,6 +16,9 @@ worklog-opsdevnz --version
16
16
 
17
17
  # Override the editor for this run
18
18
  worklog-opsdevnz --editor nvim
19
+
20
+ # Open the most recent previous entry
21
+ worklog-opsdevnz -p
19
22
  ```
20
23
 
21
24
  ## Configuration
@@ -51,6 +54,7 @@ title = "Next"
51
54
  - Configurable section headers per project
52
55
  - Custom body templates with `{{DATE}}` and `{{TITLE}}` placeholders
53
56
  - Editor integration: `-e` flag → config → `$VISUAL` → `$EDITOR`
57
+ - `-p` / `--previous` flag to open the most recent past entry
54
58
  - `--version` flag for installed version
55
59
 
56
60
  ## Requirements
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "worklog-opsdevnz"
7
- version = "0.2.0"
7
+ version = "0.2.1"
8
8
  description = "Configurable worklog management CLI for dated development logs"
9
9
  readme = "README.md"
10
10
  license = {text = "Apache-2.0"}
@@ -65,6 +65,11 @@ addopts = "-v --cov=src/worklog_opsdevnz --cov-report=term-missing"
65
65
  line-length = 88
66
66
  target-version = "py312"
67
67
 
68
+ # Explicit rule set (ruff's historical defaults) so CI is stable across
69
+ # ruff upgrades — DTZ/I/etc. are intentionally not enabled: local-date
70
+ # handling is this tool's core domain, not an oversight.
71
+ lint.select = ["E4", "E7", "E9", "F"]
72
+
68
73
  [tool.mypy]
69
74
  python_version = "3.12"
70
75
  warn_return_any = true
@@ -9,7 +9,7 @@ import click
9
9
 
10
10
  from worklog_opsdevnz import __version__
11
11
  from worklog_opsdevnz.config import get_config
12
- from worklog_opsdevnz.paths import resolve_path
12
+ from worklog_opsdevnz.paths import find_previous, resolve_path
13
13
  from worklog_opsdevnz.template import generate_content
14
14
 
15
15
 
@@ -21,11 +21,27 @@ from worklog_opsdevnz.template import generate_content
21
21
  default=None,
22
22
  help="Override the editor command (overrides config, $VISUAL, $EDITOR).",
23
23
  )
24
- def main(editor: str | None) -> None:
25
- """Create or open today's worklog entry."""
24
+ @click.option(
25
+ "-p",
26
+ "--previous",
27
+ is_flag=True,
28
+ help="Open the most recent worklog entry before today (never creates).",
29
+ )
30
+ def main(editor: str | None, previous: bool) -> None:
31
+ """Create or open today's worklog entry, or the previous one with -p."""
26
32
  entry_date = date.today()
27
33
 
28
34
  config = get_config()
35
+
36
+ if previous:
37
+ target = find_previous(config, entry_date)
38
+ if target is None:
39
+ click.echo("No previous worklog entry found.", err=True)
40
+ return
41
+ print(f"Opening previous worklog: {target}")
42
+ _open_editor(target, editor, config.get("editor"))
43
+ return
44
+
29
45
  target = resolve_path(config, entry_date)
30
46
  target.parent.mkdir(parents=True, exist_ok=True)
31
47
 
@@ -0,0 +1,73 @@
1
+ """Path resolution for worklog files."""
2
+
3
+ from datetime import date, datetime
4
+ from pathlib import Path
5
+ from typing import Any
6
+
7
+
8
+ def resolve_path(
9
+ config: dict[str, Any],
10
+ entry_date: date,
11
+ ) -> Path:
12
+ """Compute the target file path based on config structure."""
13
+ base = Path(config.get("worklog_dir", "docs/worklog"))
14
+ structure = config.get("structure", "year")
15
+ suffix = config.get("suffix", "worklog")
16
+
17
+ if structure == "flat":
18
+ filename = f"{entry_date.isoformat()}-{suffix}.md"
19
+ return base / filename
20
+ elif structure == "year-month":
21
+ year = entry_date.strftime("%Y")
22
+ month = entry_date.strftime("%m")
23
+ filename = f"{entry_date.strftime('%d-%m-%Y')}-{suffix}.md"
24
+ return base / year / month / filename
25
+ else: # "year" (default)
26
+ year = entry_date.strftime("%Y")
27
+ filename = f"{entry_date.strftime('%d-%m-%Y')}-{suffix}.md"
28
+ return base / year / filename
29
+
30
+
31
+ _DATE_FORMATS = ("%Y-%m-%d", "%d-%m-%Y")
32
+
33
+
34
+ def _parse_entry_date(filename: str, suffix: str) -> date | None:
35
+ """Extract the entry date from a worklog filename, or None if not parseable."""
36
+ stem = filename.removesuffix(".md")
37
+ prefix = stem.removesuffix(f"-{suffix}")
38
+ for fmt in _DATE_FORMATS:
39
+ try:
40
+ return datetime.strptime(prefix, fmt).date()
41
+ except ValueError:
42
+ continue
43
+ return None
44
+
45
+
46
+ def find_previous(config: dict[str, Any], today: date) -> Path | None:
47
+ """Locate the most recent worklog entry strictly before *today*.
48
+
49
+ Scans the directory tree implied by the configured structure mode
50
+ (flat, year, or year-month) for files matching ``*-{suffix}.md``,
51
+ parses their dates, and returns the newest one older than today.
52
+ Returns None when no previous entry exists. Never creates anything.
53
+ """
54
+ base = Path(config.get("worklog_dir", "docs/worklog"))
55
+ suffix = config.get("suffix", "worklog")
56
+ structure = config.get("structure", "year")
57
+
58
+ pattern = f"*-{suffix}.md"
59
+ if structure == "flat":
60
+ candidates = base.glob(pattern)
61
+ elif structure == "year-month":
62
+ candidates = base.glob(f"*/*/{pattern}")
63
+ else: # "year" (default)
64
+ candidates = base.glob(f"*/{pattern}")
65
+
66
+ best: tuple[date, Path] | None = None
67
+ for path in candidates:
68
+ entry_date = _parse_entry_date(path.name, suffix)
69
+ if entry_date is None or entry_date >= today:
70
+ continue
71
+ if best is None or entry_date > best[0]:
72
+ best = (entry_date, path)
73
+ return best[1] if best else None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: worklog-opsdevnz
3
- Version: 0.2.0
3
+ Version: 0.2.1
4
4
  Summary: Configurable worklog management CLI for dated development logs
5
5
  Author-email: "OpsDev.nz Collective" <john@opsdev.nz>
6
6
  License: Apache-2.0
@@ -50,6 +50,9 @@ worklog-opsdevnz --version
50
50
 
51
51
  # Override the editor for this run
52
52
  worklog-opsdevnz --editor nvim
53
+
54
+ # Open the most recent previous entry
55
+ worklog-opsdevnz -p
53
56
  ```
54
57
 
55
58
  ## Configuration
@@ -85,6 +88,7 @@ title = "Next"
85
88
  - Configurable section headers per project
86
89
  - Custom body templates with `{{DATE}}` and `{{TITLE}}` placeholders
87
90
  - Editor integration: `-e` flag → config → `$VISUAL` → `$EDITOR`
91
+ - `-p` / `--previous` flag to open the most recent past entry
88
92
  - `--version` flag for installed version
89
93
 
90
94
  ## Requirements
@@ -0,0 +1,137 @@
1
+ """Tests for CLI entry point."""
2
+
3
+ from datetime import date, timedelta
4
+
5
+ from click.testing import CliRunner
6
+
7
+ from worklog_opsdevnz.cli import main
8
+
9
+
10
+ def test_main_creates_file(tmp_path, monkeypatch):
11
+ """Running with no args creates today's worklog in tmp_path."""
12
+ monkeypatch.chdir(tmp_path)
13
+ runner = CliRunner()
14
+ result = runner.invoke(main, [])
15
+ assert result.exit_code == 0
16
+ assert "Created" in result.output
17
+ expected_leaf = (
18
+ f"docs/worklog/{date.today().year}/{date.today():%d-%m-%Y}-worklog.md"
19
+ )
20
+ assert expected_leaf in result.output
21
+
22
+
23
+ def test_main_opens_existing(tmp_path, monkeypatch):
24
+ """Running again opens the existing file."""
25
+ monkeypatch.chdir(tmp_path)
26
+ runner = CliRunner()
27
+ runner.invoke(main, [])
28
+ result = runner.invoke(main, [])
29
+ assert result.exit_code == 0
30
+ assert "Opening existing" in result.output
31
+
32
+
33
+ def test_main_help():
34
+ """--help works."""
35
+ runner = CliRunner()
36
+ result = runner.invoke(main, ["--help"])
37
+ assert result.exit_code == 0
38
+ assert "--editor" in result.output
39
+
40
+
41
+ def test_main_version():
42
+ """--version prints the installed version."""
43
+ runner = CliRunner()
44
+ result = runner.invoke(main, ["--version"])
45
+ assert result.exit_code == 0
46
+ assert "worklog-opsdevnz, version" in result.output
47
+ # Extract and verify it's a non-empty version string
48
+ version_str = result.output.strip().split(", version ")[-1]
49
+ assert version_str
50
+
51
+
52
+ def test_main_editor_from_config(tmp_path, monkeypatch):
53
+ """Editor in worklog.toml is resolved before $VISUAL/$EDITOR."""
54
+ monkeypatch.chdir(tmp_path)
55
+ (tmp_path / "worklog.toml").write_text('editor = "fake-editor-test"\n')
56
+ runner = CliRunner()
57
+ result = runner.invoke(main, [])
58
+ assert result.exit_code == 0
59
+ # config-based editor picked up but not found in PATH
60
+ assert "Editor 'fake-editor-test' not found" in result.output
61
+
62
+
63
+ def test_main_editor_cli_overrides_config(tmp_path, monkeypatch):
64
+ """-e flag overrides the editor set in worklog.toml."""
65
+ monkeypatch.chdir(tmp_path)
66
+ (tmp_path / "worklog.toml").write_text('editor = "fake-editor-test"\n')
67
+ runner = CliRunner()
68
+ result = runner.invoke(main, ["-e", "override-editor-test"])
69
+ assert result.exit_code == 0
70
+ # CLI override takes priority over config
71
+ assert "Editor 'override-editor-test' not found" in result.output
72
+
73
+
74
+ def test_previous_no_entries(tmp_path, monkeypatch):
75
+ """-p with no prior entries: message to stderr, exit 0, creates nothing."""
76
+ monkeypatch.chdir(tmp_path)
77
+ runner = CliRunner()
78
+ result = runner.invoke(main, ["-p"])
79
+ assert result.exit_code == 0
80
+ assert "No previous worklog entry found." in result.stderr
81
+ assert not (tmp_path / "docs").exists()
82
+
83
+
84
+ def test_previous_opens_most_recent_before_today(tmp_path, monkeypatch):
85
+ """-p opens the newest prior entry, not today's, and creates no file."""
86
+ monkeypatch.chdir(tmp_path)
87
+ today = date.today()
88
+ year_dir = tmp_path / "docs" / "worklog" / str(today.year)
89
+ year_dir.mkdir(parents=True)
90
+ older = (today - timedelta(days=3)).strftime("%d-%m-%Y")
91
+ recent = (today - timedelta(days=1)).strftime("%d-%m-%Y")
92
+ (year_dir / f"{older}-worklog.md").write_text("older")
93
+ (year_dir / f"{recent}-worklog.md").write_text("recent")
94
+ today_file = year_dir / f"{today:%d-%m-%Y}-worklog.md"
95
+ today_file.write_text("today")
96
+
97
+ runner = CliRunner()
98
+ result = runner.invoke(main, ["--previous"])
99
+ assert result.exit_code == 0
100
+ assert recent in result.output
101
+ assert today.strftime("%d-%m-%Y") not in result.output
102
+
103
+
104
+ def test_previous_does_not_create_today(tmp_path, monkeypatch):
105
+ """-p must not create today's entry even though it does not exist."""
106
+ monkeypatch.chdir(tmp_path)
107
+ today = date.today()
108
+ year_dir = tmp_path / "docs" / "worklog" / str(today.year)
109
+ year_dir.mkdir(parents=True)
110
+ (year_dir / f"{(today - timedelta(days=2)):%d-%m-%Y}-worklog.md").write_text("x")
111
+
112
+ runner = CliRunner()
113
+ runner.invoke(main, ["-p"])
114
+ assert not (year_dir / f"{today:%d-%m-%Y}-worklog.md").exists()
115
+
116
+
117
+ def test_previous_editor_override(tmp_path, monkeypatch):
118
+ """-p combined with -e applies the editor override to the previous entry."""
119
+ monkeypatch.chdir(tmp_path)
120
+ today = date.today()
121
+ year_dir = tmp_path / "docs" / "worklog" / str(today.year)
122
+ year_dir.mkdir(parents=True)
123
+ recent = (today - timedelta(days=1)).strftime("%d-%m-%Y")
124
+ (year_dir / f"{recent}-worklog.md").write_text("recent")
125
+
126
+ runner = CliRunner()
127
+ result = runner.invoke(main, ["-p", "-e", "override-editor-test"])
128
+ assert result.exit_code == 0
129
+ assert "Editor 'override-editor-test' not found" in result.output
130
+
131
+
132
+ def test_previous_help():
133
+ """--help mentions the --previous flag."""
134
+ runner = CliRunner()
135
+ result = runner.invoke(main, ["--help"])
136
+ assert result.exit_code == 0
137
+ assert "--previous" in result.output
@@ -0,0 +1,79 @@
1
+ """Tests for path resolution."""
2
+
3
+ from datetime import date
4
+
5
+ from worklog_opsdevnz.paths import find_previous, resolve_path
6
+
7
+
8
+ def test_resolve_path_flat():
9
+ config = {"worklog_dir": "docs/worklog", "structure": "flat", "suffix": "worklog"}
10
+ path = resolve_path(config, date(2026, 5, 23))
11
+ assert str(path) == "docs/worklog/2026-05-23-worklog.md"
12
+
13
+
14
+ def test_resolve_path_year():
15
+ config = {"worklog_dir": "logs", "structure": "year", "suffix": "log"}
16
+ path = resolve_path(config, date(2026, 5, 23))
17
+ assert str(path) == "logs/2026/23-05-2026-log.md"
18
+
19
+
20
+ def test_resolve_path_year_month():
21
+ config = {"worklog_dir": "logs", "structure": "year-month", "suffix": "ops"}
22
+ path = resolve_path(config, date(2026, 5, 23))
23
+ assert str(path) == "logs/2026/05/23-05-2026-ops.md"
24
+
25
+
26
+ def test_resolve_path_custom_suffix():
27
+ config = {"structure": "year", "suffix": "retro"}
28
+ path = resolve_path(config, date(2026, 1, 1))
29
+ assert str(path).endswith("-retro.md")
30
+
31
+
32
+ def test_find_previous_year(tmp_path):
33
+ base = tmp_path / "logs" / "2026"
34
+ base.mkdir(parents=True)
35
+ (base / "28-08-2026-worklog.md").write_text("old")
36
+ (base / "01-09-2026-worklog.md").write_text("prev")
37
+ (base / "03-09-2026-worklog.md").write_text("today")
38
+ config = {"worklog_dir": str(tmp_path / "logs"), "structure": "year", "suffix": "worklog"}
39
+ result = find_previous(config, date(2026, 9, 3))
40
+ assert result is not None
41
+ assert result.name == "01-09-2026-worklog.md"
42
+
43
+
44
+ def test_find_previous_year_month(tmp_path):
45
+ base = tmp_path / "docs" / "worklogs"
46
+ (base / "2026" / "08").mkdir(parents=True)
47
+ (base / "2026" / "09").mkdir(parents=True)
48
+ (base / "2026" / "08" / "27-08-2026-worklog.md").write_text("aug")
49
+ (base / "2026" / "09" / "01-09-2026-worklog.md").write_text("sep")
50
+ config = {"worklog_dir": str(base), "structure": "year-month", "suffix": "worklog"}
51
+ result = find_previous(config, date(2026, 9, 2))
52
+ assert result is not None
53
+ assert result.name == "01-09-2026-worklog.md"
54
+
55
+
56
+ def test_find_previous_flat_iso_names(tmp_path):
57
+ base = tmp_path / "wl"
58
+ base.mkdir()
59
+ (base / "2026-08-30-worklog.md").write_text("a")
60
+ (base / "2026-09-01-worklog.md").write_text("b")
61
+ config = {"worklog_dir": str(base), "structure": "flat", "suffix": "worklog"}
62
+ result = find_previous(config, date(2026, 9, 2))
63
+ assert result is not None
64
+ assert result.name == "2026-09-01-worklog.md"
65
+
66
+
67
+ def test_find_previous_ignores_today_unrelated_and_wrong_suffix(tmp_path):
68
+ base = tmp_path / "logs" / "2026"
69
+ base.mkdir(parents=True)
70
+ (base / "03-09-2026-worklog.md").write_text("today")
71
+ (base / "README.md").write_text("not an entry")
72
+ (base / "01-09-2026-journal.md").write_text("wrong suffix")
73
+ config = {"worklog_dir": str(tmp_path / "logs"), "structure": "year", "suffix": "worklog"}
74
+ assert find_previous(config, date(2026, 9, 3)) is None
75
+
76
+
77
+ def test_find_previous_missing_dir(tmp_path):
78
+ config = {"worklog_dir": str(tmp_path / "nothing"), "structure": "year", "suffix": "worklog"}
79
+ assert find_previous(config, date(2026, 9, 3)) is None
@@ -1,28 +0,0 @@
1
- """Path resolution for worklog files."""
2
-
3
- from datetime import date
4
- from pathlib import Path
5
- from typing import Any
6
-
7
-
8
- def resolve_path(
9
- config: dict[str, Any],
10
- entry_date: date,
11
- ) -> Path:
12
- """Compute the target file path based on config structure."""
13
- base = Path(config.get("worklog_dir", "docs/worklog"))
14
- structure = config.get("structure", "year")
15
- suffix = config.get("suffix", "worklog")
16
-
17
- if structure == "flat":
18
- filename = f"{entry_date.isoformat()}-{suffix}.md"
19
- return base / filename
20
- elif structure == "year-month":
21
- year = entry_date.strftime("%Y")
22
- month = entry_date.strftime("%m")
23
- filename = f"{entry_date.strftime('%d-%m-%Y')}-{suffix}.md"
24
- return base / year / month / filename
25
- else: # "year" (default)
26
- year = entry_date.strftime("%Y")
27
- filename = f"{entry_date.strftime('%d-%m-%Y')}-{suffix}.md"
28
- return base / year / filename
@@ -1,71 +0,0 @@
1
- """Tests for CLI entry point."""
2
-
3
- from datetime import date
4
-
5
- from click.testing import CliRunner
6
-
7
- from worklog_opsdevnz.cli import main
8
-
9
-
10
- def test_main_creates_file(tmp_path, monkeypatch):
11
- """Running with no args creates today's worklog in tmp_path."""
12
- monkeypatch.chdir(tmp_path)
13
- runner = CliRunner()
14
- result = runner.invoke(main, [])
15
- assert result.exit_code == 0
16
- assert "Created" in result.output
17
- expected_leaf = (
18
- f"docs/worklog/{date.today().year}/{date.today():%d-%m-%Y}-worklog.md"
19
- )
20
- assert expected_leaf in result.output
21
-
22
-
23
- def test_main_opens_existing(tmp_path, monkeypatch):
24
- """Running again opens the existing file."""
25
- monkeypatch.chdir(tmp_path)
26
- runner = CliRunner()
27
- runner.invoke(main, [])
28
- result = runner.invoke(main, [])
29
- assert result.exit_code == 0
30
- assert "Opening existing" in result.output
31
-
32
-
33
- def test_main_help():
34
- """--help works."""
35
- runner = CliRunner()
36
- result = runner.invoke(main, ["--help"])
37
- assert result.exit_code == 0
38
- assert "--editor" in result.output
39
-
40
-
41
- def test_main_version():
42
- """--version prints the installed version."""
43
- runner = CliRunner()
44
- result = runner.invoke(main, ["--version"])
45
- assert result.exit_code == 0
46
- assert "worklog-opsdevnz, version" in result.output
47
- # Extract and verify it's a non-empty version string
48
- version_str = result.output.strip().split(", version ")[-1]
49
- assert version_str
50
-
51
-
52
- def test_main_editor_from_config(tmp_path, monkeypatch):
53
- """Editor in worklog.toml is resolved before $VISUAL/$EDITOR."""
54
- monkeypatch.chdir(tmp_path)
55
- (tmp_path / "worklog.toml").write_text('editor = "fake-editor-test"\n')
56
- runner = CliRunner()
57
- result = runner.invoke(main, [])
58
- assert result.exit_code == 0
59
- # config-based editor picked up but not found in PATH
60
- assert "Editor 'fake-editor-test' not found" in result.output
61
-
62
-
63
- def test_main_editor_cli_overrides_config(tmp_path, monkeypatch):
64
- """-e flag overrides the editor set in worklog.toml."""
65
- monkeypatch.chdir(tmp_path)
66
- (tmp_path / "worklog.toml").write_text('editor = "fake-editor-test"\n')
67
- runner = CliRunner()
68
- result = runner.invoke(main, ["-e", "override-editor-test"])
69
- assert result.exit_code == 0
70
- # CLI override takes priority over config
71
- assert "Editor 'override-editor-test' not found" in result.output
@@ -1,29 +0,0 @@
1
- """Tests for path resolution."""
2
-
3
- from datetime import date
4
-
5
- from worklog_opsdevnz.paths import resolve_path
6
-
7
-
8
- def test_resolve_path_flat():
9
- config = {"worklog_dir": "docs/worklog", "structure": "flat", "suffix": "worklog"}
10
- path = resolve_path(config, date(2026, 5, 23))
11
- assert str(path) == "docs/worklog/2026-05-23-worklog.md"
12
-
13
-
14
- def test_resolve_path_year():
15
- config = {"worklog_dir": "logs", "structure": "year", "suffix": "log"}
16
- path = resolve_path(config, date(2026, 5, 23))
17
- assert str(path) == "logs/2026/23-05-2026-log.md"
18
-
19
-
20
- def test_resolve_path_year_month():
21
- config = {"worklog_dir": "logs", "structure": "year-month", "suffix": "ops"}
22
- path = resolve_path(config, date(2026, 5, 23))
23
- assert str(path) == "logs/2026/05/23-05-2026-ops.md"
24
-
25
-
26
- def test_resolve_path_custom_suffix():
27
- config = {"structure": "year", "suffix": "retro"}
28
- path = resolve_path(config, date(2026, 1, 1))
29
- assert str(path).endswith("-retro.md")