worklog-opsdevnz 0.1.2__tar.gz → 0.1.3__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.
- {worklog_opsdevnz-0.1.2/src/worklog_opsdevnz.egg-info → worklog_opsdevnz-0.1.3}/PKG-INFO +3 -1
- {worklog_opsdevnz-0.1.2 → worklog_opsdevnz-0.1.3}/README.md +2 -0
- {worklog_opsdevnz-0.1.2 → worklog_opsdevnz-0.1.3}/pyproject.toml +1 -1
- {worklog_opsdevnz-0.1.2 → worklog_opsdevnz-0.1.3}/src/worklog_opsdevnz/config.py +3 -0
- {worklog_opsdevnz-0.1.2 → worklog_opsdevnz-0.1.3}/src/worklog_opsdevnz/template.py +23 -2
- {worklog_opsdevnz-0.1.2 → worklog_opsdevnz-0.1.3/src/worklog_opsdevnz.egg-info}/PKG-INFO +3 -1
- worklog_opsdevnz-0.1.3/tests/test_template.py +99 -0
- worklog_opsdevnz-0.1.2/tests/test_template.py +0 -45
- {worklog_opsdevnz-0.1.2 → worklog_opsdevnz-0.1.3}/LICENSE +0 -0
- {worklog_opsdevnz-0.1.2 → worklog_opsdevnz-0.1.3}/setup.cfg +0 -0
- {worklog_opsdevnz-0.1.2 → worklog_opsdevnz-0.1.3}/src/worklog_opsdevnz/__init__.py +0 -0
- {worklog_opsdevnz-0.1.2 → worklog_opsdevnz-0.1.3}/src/worklog_opsdevnz/cli.py +0 -0
- {worklog_opsdevnz-0.1.2 → worklog_opsdevnz-0.1.3}/src/worklog_opsdevnz/paths.py +0 -0
- {worklog_opsdevnz-0.1.2 → worklog_opsdevnz-0.1.3}/src/worklog_opsdevnz.egg-info/SOURCES.txt +0 -0
- {worklog_opsdevnz-0.1.2 → worklog_opsdevnz-0.1.3}/src/worklog_opsdevnz.egg-info/dependency_links.txt +0 -0
- {worklog_opsdevnz-0.1.2 → worklog_opsdevnz-0.1.3}/src/worklog_opsdevnz.egg-info/entry_points.txt +0 -0
- {worklog_opsdevnz-0.1.2 → worklog_opsdevnz-0.1.3}/src/worklog_opsdevnz.egg-info/requires.txt +0 -0
- {worklog_opsdevnz-0.1.2 → worklog_opsdevnz-0.1.3}/src/worklog_opsdevnz.egg-info/top_level.txt +0 -0
- {worklog_opsdevnz-0.1.2 → worklog_opsdevnz-0.1.3}/tests/test_cli.py +0 -0
- {worklog_opsdevnz-0.1.2 → worklog_opsdevnz-0.1.3}/tests/test_config.py +0 -0
- {worklog_opsdevnz-0.1.2 → worklog_opsdevnz-0.1.3}/tests/test_paths.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: worklog-opsdevnz
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.3
|
|
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
|
|
@@ -60,6 +60,7 @@ worklog_dir = "docs/worklog"
|
|
|
60
60
|
structure = "year" # "flat", "year", or "year-month"
|
|
61
61
|
author = "Your Name"
|
|
62
62
|
editor = "nvim" # optional, overridden by -e / $VISUAL / $EDITOR
|
|
63
|
+
template = "my-template.md" # optional custom body template
|
|
63
64
|
default_tags = ["worklog", "log"]
|
|
64
65
|
|
|
65
66
|
[[sections]]
|
|
@@ -81,6 +82,7 @@ title = "Next"
|
|
|
81
82
|
- Three directory structure modes: `flat`, `year`, `year-month`
|
|
82
83
|
- YAML frontmatter: date, author, tags, draft status
|
|
83
84
|
- Configurable section headers per project
|
|
85
|
+
- Custom body templates with `{{DATE}}` and `{{TITLE}}` placeholders
|
|
84
86
|
- Editor integration: `-e` flag → config → `$VISUAL` → `$EDITOR`
|
|
85
87
|
- `--version` flag for installed version
|
|
86
88
|
|
|
@@ -27,6 +27,7 @@ worklog_dir = "docs/worklog"
|
|
|
27
27
|
structure = "year" # "flat", "year", or "year-month"
|
|
28
28
|
author = "Your Name"
|
|
29
29
|
editor = "nvim" # optional, overridden by -e / $VISUAL / $EDITOR
|
|
30
|
+
template = "my-template.md" # optional custom body template
|
|
30
31
|
default_tags = ["worklog", "log"]
|
|
31
32
|
|
|
32
33
|
[[sections]]
|
|
@@ -48,6 +49,7 @@ title = "Next"
|
|
|
48
49
|
- Three directory structure modes: `flat`, `year`, `year-month`
|
|
49
50
|
- YAML frontmatter: date, author, tags, draft status
|
|
50
51
|
- Configurable section headers per project
|
|
52
|
+
- Custom body templates with `{{DATE}}` and `{{TITLE}}` placeholders
|
|
51
53
|
- Editor integration: `-e` flag → config → `$VISUAL` → `$EDITOR`
|
|
52
54
|
- `--version` flag for installed version
|
|
53
55
|
|
|
@@ -67,5 +67,8 @@ def get_config() -> dict[str, Any]:
|
|
|
67
67
|
worklog_dir = merged["worklog_dir"]
|
|
68
68
|
if not Path(worklog_dir).is_absolute():
|
|
69
69
|
merged["worklog_dir"] = str(config_path.parent / worklog_dir)
|
|
70
|
+
template = merged.get("template")
|
|
71
|
+
if template and not Path(template).is_absolute():
|
|
72
|
+
merged["template"] = str(config_path.parent / template)
|
|
70
73
|
return merged
|
|
71
74
|
return dict(DEFAULT_CONFIG)
|
|
@@ -36,11 +36,32 @@ def generate_body(config: dict[str, Any]) -> str:
|
|
|
36
36
|
return "\n".join(lines)
|
|
37
37
|
|
|
38
38
|
|
|
39
|
+
def render_template(template_path: str, iso_date: str) -> str:
|
|
40
|
+
"""Render a custom Markdown template with placeholder substitution."""
|
|
41
|
+
title = f"Work Log - {iso_date}"
|
|
42
|
+
with open(template_path) as f:
|
|
43
|
+
content = f.read()
|
|
44
|
+
content = content.replace("{{DATE}}", iso_date)
|
|
45
|
+
content = content.replace("{{TITLE}}", title)
|
|
46
|
+
return content
|
|
47
|
+
|
|
48
|
+
|
|
39
49
|
def generate_content(
|
|
40
50
|
config: dict[str, Any],
|
|
41
51
|
iso_date: str,
|
|
42
52
|
) -> str:
|
|
43
|
-
"""Generate full worklog content.
|
|
53
|
+
"""Generate full worklog content.
|
|
54
|
+
|
|
55
|
+
If a 'template' field is set in config, renders that file as the body.
|
|
56
|
+
Otherwise uses the built-in sections-based body.
|
|
57
|
+
Frontmatter is always generated regardless of template.
|
|
58
|
+
"""
|
|
44
59
|
frontmatter = generate_frontmatter(config, iso_date)
|
|
45
|
-
|
|
60
|
+
|
|
61
|
+
template_path = config.get("template")
|
|
62
|
+
if template_path:
|
|
63
|
+
body = render_template(template_path, iso_date)
|
|
64
|
+
else:
|
|
65
|
+
body = generate_body(config)
|
|
66
|
+
|
|
46
67
|
return f"{frontmatter}\n{body}"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: worklog-opsdevnz
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.3
|
|
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
|
|
@@ -60,6 +60,7 @@ worklog_dir = "docs/worklog"
|
|
|
60
60
|
structure = "year" # "flat", "year", or "year-month"
|
|
61
61
|
author = "Your Name"
|
|
62
62
|
editor = "nvim" # optional, overridden by -e / $VISUAL / $EDITOR
|
|
63
|
+
template = "my-template.md" # optional custom body template
|
|
63
64
|
default_tags = ["worklog", "log"]
|
|
64
65
|
|
|
65
66
|
[[sections]]
|
|
@@ -81,6 +82,7 @@ title = "Next"
|
|
|
81
82
|
- Three directory structure modes: `flat`, `year`, `year-month`
|
|
82
83
|
- YAML frontmatter: date, author, tags, draft status
|
|
83
84
|
- Configurable section headers per project
|
|
85
|
+
- Custom body templates with `{{DATE}}` and `{{TITLE}}` placeholders
|
|
84
86
|
- Editor integration: `-e` flag → config → `$VISUAL` → `$EDITOR`
|
|
85
87
|
- `--version` flag for installed version
|
|
86
88
|
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"""Tests for frontmatter and body generation."""
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
|
|
5
|
+
from worklog_opsdevnz.template import (
|
|
6
|
+
generate_frontmatter,
|
|
7
|
+
generate_body,
|
|
8
|
+
generate_content,
|
|
9
|
+
render_template,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def test_generate_frontmatter():
|
|
14
|
+
config = {
|
|
15
|
+
"author": "Test Author",
|
|
16
|
+
"default_tags": ["internal", "test"],
|
|
17
|
+
}
|
|
18
|
+
fm = generate_frontmatter(config, "2026-05-23")
|
|
19
|
+
assert "title: " in fm
|
|
20
|
+
assert "Work Log - 2026-05-23" in fm
|
|
21
|
+
assert "date: 2026-05-23" in fm
|
|
22
|
+
assert "author: Test Author" in fm
|
|
23
|
+
assert " - internal" in fm
|
|
24
|
+
assert " - test" in fm
|
|
25
|
+
assert "draft: false" in fm
|
|
26
|
+
assert fm.startswith("---")
|
|
27
|
+
assert fm.strip().endswith("---")
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def test_generate_body_with_sections():
|
|
31
|
+
config = {
|
|
32
|
+
"sections": [
|
|
33
|
+
{"title": "Focus", "content": ""},
|
|
34
|
+
{"title": "Notes", "content": "some note"},
|
|
35
|
+
]
|
|
36
|
+
}
|
|
37
|
+
body = generate_body(config)
|
|
38
|
+
assert "## Focus" in body
|
|
39
|
+
assert "## Notes" in body
|
|
40
|
+
assert "some note" in body
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def test_generate_content_full():
|
|
44
|
+
config = {
|
|
45
|
+
"author": "opsdev",
|
|
46
|
+
"default_tags": ["log"],
|
|
47
|
+
"sections": [{"title": "Today", "content": ""}],
|
|
48
|
+
}
|
|
49
|
+
content = generate_content(config, "2026-05-23")
|
|
50
|
+
assert content.startswith("---")
|
|
51
|
+
assert "Work Log - 2026-05-23" in content
|
|
52
|
+
assert "## Today" in content
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def test_render_template_with_placeholders(tmp_path):
|
|
56
|
+
template = tmp_path / "my-template.md"
|
|
57
|
+
template.write_text("# {{TITLE}}\n\nDate: {{DATE}}\n\nFree-form notes.")
|
|
58
|
+
|
|
59
|
+
result = render_template(str(template), "2026-05-26")
|
|
60
|
+
assert "# Work Log - 2026-05-26" in result
|
|
61
|
+
assert "Date: 2026-05-26" in result
|
|
62
|
+
assert "Free-form notes." in result
|
|
63
|
+
assert "{{DATE}}" not in result
|
|
64
|
+
assert "{{TITLE}}" not in result
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def test_render_template_file_not_found():
|
|
68
|
+
with pytest.raises(FileNotFoundError):
|
|
69
|
+
render_template("/nonexistent/template.md", "2026-05-26")
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def test_generate_content_with_template(tmp_path):
|
|
73
|
+
template = tmp_path / "my-template.md"
|
|
74
|
+
template.write_text("# {{TITLE}}\n\nDate: {{DATE}}")
|
|
75
|
+
|
|
76
|
+
config = {
|
|
77
|
+
"author": "opsdev",
|
|
78
|
+
"default_tags": ["log"],
|
|
79
|
+
"template": str(template),
|
|
80
|
+
}
|
|
81
|
+
content = generate_content(config, "2026-05-26")
|
|
82
|
+
assert content.startswith("---")
|
|
83
|
+
assert "Work Log - 2026-05-26" in content
|
|
84
|
+
assert "author: opsdev" in content
|
|
85
|
+
assert "# Work Log - 2026-05-26" in content
|
|
86
|
+
assert "Date: 2026-05-26" in content
|
|
87
|
+
# Frontmatter generated, body from template — not sections
|
|
88
|
+
assert "## " not in content.split("---\n")[2] if "---\n" in content else True
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def test_generate_content_without_template():
|
|
92
|
+
"""No template field → built-in sections body, unchanged behaviour."""
|
|
93
|
+
config = {
|
|
94
|
+
"author": "opsdev",
|
|
95
|
+
"default_tags": ["log"],
|
|
96
|
+
"sections": [{"title": "Today", "content": ""}],
|
|
97
|
+
}
|
|
98
|
+
content = generate_content(config, "2026-05-26")
|
|
99
|
+
assert "## Today" in content
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
"""Tests for frontmatter and body generation."""
|
|
2
|
-
|
|
3
|
-
from worklog_opsdevnz.template import generate_frontmatter, generate_body, generate_content
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
def test_generate_frontmatter():
|
|
7
|
-
config = {
|
|
8
|
-
"author": "Test Author",
|
|
9
|
-
"default_tags": ["internal", "test"],
|
|
10
|
-
}
|
|
11
|
-
fm = generate_frontmatter(config, "2026-05-23")
|
|
12
|
-
assert "title: " in fm
|
|
13
|
-
assert "Work Log - 2026-05-23" in fm
|
|
14
|
-
assert "date: 2026-05-23" in fm
|
|
15
|
-
assert "author: Test Author" in fm
|
|
16
|
-
assert " - internal" in fm
|
|
17
|
-
assert " - test" in fm
|
|
18
|
-
assert "draft: false" in fm
|
|
19
|
-
assert fm.startswith("---")
|
|
20
|
-
assert fm.strip().endswith("---")
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
def test_generate_body_with_sections():
|
|
24
|
-
config = {
|
|
25
|
-
"sections": [
|
|
26
|
-
{"title": "Focus", "content": ""},
|
|
27
|
-
{"title": "Notes", "content": "some note"},
|
|
28
|
-
]
|
|
29
|
-
}
|
|
30
|
-
body = generate_body(config)
|
|
31
|
-
assert "## Focus" in body
|
|
32
|
-
assert "## Notes" in body
|
|
33
|
-
assert "some note" in body
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
def test_generate_content_full():
|
|
37
|
-
config = {
|
|
38
|
-
"author": "opsdev",
|
|
39
|
-
"default_tags": ["log"],
|
|
40
|
-
"sections": [{"title": "Today", "content": ""}],
|
|
41
|
-
}
|
|
42
|
-
content = generate_content(config, "2026-05-23")
|
|
43
|
-
assert content.startswith("---")
|
|
44
|
-
assert "Work Log - 2026-05-23" in content
|
|
45
|
-
assert "## Today" in content
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{worklog_opsdevnz-0.1.2 → worklog_opsdevnz-0.1.3}/src/worklog_opsdevnz.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{worklog_opsdevnz-0.1.2 → worklog_opsdevnz-0.1.3}/src/worklog_opsdevnz.egg-info/entry_points.txt
RENAMED
|
File without changes
|
{worklog_opsdevnz-0.1.2 → worklog_opsdevnz-0.1.3}/src/worklog_opsdevnz.egg-info/requires.txt
RENAMED
|
File without changes
|
{worklog_opsdevnz-0.1.2 → worklog_opsdevnz-0.1.3}/src/worklog_opsdevnz.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|