clockify-export 0.3.0__tar.gz → 0.3.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 (32) hide show
  1. {clockify_export-0.3.0 → clockify_export-0.3.1}/CHANGELOG.md +5 -0
  2. {clockify_export-0.3.0 → clockify_export-0.3.1}/PKG-INFO +2 -1
  3. {clockify_export-0.3.0 → clockify_export-0.3.1}/README.md +1 -0
  4. {clockify_export-0.3.0 → clockify_export-0.3.1}/pyproject.toml +1 -1
  5. clockify_export-0.3.1/src/clockify_export/systemd_install.py +55 -0
  6. {clockify_export-0.3.0 → clockify_export-0.3.1}/tests/test_cli.py +13 -0
  7. {clockify_export-0.3.0 → clockify_export-0.3.1}/uv.lock +1 -1
  8. clockify_export-0.3.0/src/clockify_export/systemd_install.py +0 -30
  9. {clockify_export-0.3.0 → clockify_export-0.3.1}/.env.example +0 -0
  10. {clockify_export-0.3.0 → clockify_export-0.3.1}/.github/workflows/publish.yml +0 -0
  11. {clockify_export-0.3.0 → clockify_export-0.3.1}/.gitignore +0 -0
  12. {clockify_export-0.3.0 → clockify_export-0.3.1}/.vscode/settings.json +0 -0
  13. {clockify_export-0.3.0 → clockify_export-0.3.1}/AGENTS.md +0 -0
  14. {clockify_export-0.3.0 → clockify_export-0.3.1}/LICENSE +0 -0
  15. {clockify_export-0.3.0 → clockify_export-0.3.1}/PLAN.md +0 -0
  16. {clockify_export-0.3.0 → clockify_export-0.3.1}/mise-tasks/bump-version +0 -0
  17. {clockify_export-0.3.0 → clockify_export-0.3.1}/mise.toml +0 -0
  18. {clockify_export-0.3.0 → clockify_export-0.3.1}/src/clockify_export/__init__.py +0 -0
  19. {clockify_export-0.3.0 → clockify_export-0.3.1}/src/clockify_export/api.py +0 -0
  20. {clockify_export-0.3.0 → clockify_export-0.3.1}/src/clockify_export/cache.py +0 -0
  21. {clockify_export-0.3.0 → clockify_export-0.3.1}/src/clockify_export/cli.py +0 -0
  22. {clockify_export-0.3.0 → clockify_export-0.3.1}/src/clockify_export/config.py +0 -0
  23. {clockify_export-0.3.0 → clockify_export-0.3.1}/src/clockify_export/export.py +0 -0
  24. {clockify_export-0.3.0 → clockify_export-0.3.1}/src/clockify_export/systemd/clockify-export.service +0 -0
  25. {clockify_export-0.3.0 → clockify_export-0.3.1}/src/clockify_export/systemd/clockify-export.timer +0 -0
  26. {clockify_export-0.3.0 → clockify_export-0.3.1}/systemd/clockify-export.service +0 -0
  27. {clockify_export-0.3.0 → clockify_export-0.3.1}/systemd/clockify-export.timer +0 -0
  28. {clockify_export-0.3.0 → clockify_export-0.3.1}/tests/conftest.py +0 -0
  29. {clockify_export-0.3.0 → clockify_export-0.3.1}/tests/test_api.py +0 -0
  30. {clockify_export-0.3.0 → clockify_export-0.3.1}/tests/test_cache.py +0 -0
  31. {clockify_export-0.3.0 → clockify_export-0.3.1}/tests/test_config.py +0 -0
  32. {clockify_export-0.3.0 → clockify_export-0.3.1}/tests/test_export.py +0 -0
@@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.2.1]
11
+
12
+ ### Fixed
13
+ - `--install-systemd` now uses the path of the running executable when writing the systemd service.
14
+
10
15
  ## [0.2.0]
11
16
 
12
17
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: clockify-export
3
- Version: 0.3.0
3
+ Version: 0.3.1
4
4
  Summary: Export Clockify time entries to CSV with incremental support
5
5
  Project-URL: Homepage, https://github.com/ptandler/clockify-export
6
6
  Project-URL: Repository, https://github.com/ptandler/clockify-export
@@ -138,6 +138,7 @@ clockify-export --install-systemd
138
138
  ```
139
139
 
140
140
  This copies the bundled service/timer into `~/.config/systemd/user/` and enables the timer.
141
+ The installed service writes the currently resolved `clockify-export` executable path, so installs in a different directory still work correctly.
141
142
 
142
143
  See below for other options.
143
144
 
@@ -112,6 +112,7 @@ clockify-export --install-systemd
112
112
  ```
113
113
 
114
114
  This copies the bundled service/timer into `~/.config/systemd/user/` and enables the timer.
115
+ The installed service writes the currently resolved `clockify-export` executable path, so installs in a different directory still work correctly.
115
116
 
116
117
  See below for other options.
117
118
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "clockify-export"
3
- version = "0.3.0"
3
+ version = "0.3.1"
4
4
  description = "Export Clockify time entries to CSV with incremental support"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -0,0 +1,55 @@
1
+ """Helpers for installing the daily systemd timer for clockify-export."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import shutil
6
+ import subprocess
7
+ import sys
8
+ from pathlib import Path
9
+
10
+
11
+ def _resolve_clockify_export_binary() -> str:
12
+ """Return the executable path for the installed clockify-export command."""
13
+ executable = shutil.which("clockify-export")
14
+ if executable:
15
+ return executable
16
+
17
+ # If the tool was installed in a managed environment without a PATH entry
18
+ # available to systemd, try common pipx locations as a fallback.
19
+ for candidate in (
20
+ Path.home() / ".local" / "bin" / "clockify-export",
21
+ Path.home() / ".local" / "share" / "mise" / "installs" / "pipx-clockify-export" / "latest" / "bin" / "clockify-export",
22
+ Path.home() / ".local" / "share" / "pipx" / "venvs" / "clockify-export" / "bin" / "clockify-export",
23
+ Path.home() / ".local" / "share" / "uv" / "tools" / "clockify-export" / "bin" / "clockify-export",
24
+ ):
25
+ if candidate.exists():
26
+ return str(candidate)
27
+
28
+ return "clockify-export"
29
+
30
+
31
+ def install_systemd_user_units() -> None:
32
+ """Install the user systemd timer and service for daily exports."""
33
+ target_dir = Path.home() / ".config" / "systemd" / "user"
34
+ target_dir.mkdir(parents=True, exist_ok=True)
35
+
36
+ bundled_dir = Path(__file__).resolve().parent / "systemd"
37
+ service_source = (bundled_dir / "clockify-export.service").read_text(encoding="utf-8")
38
+ service_source = service_source.replace("ExecStart=%h/.local/bin/clockify-export", f"ExecStart={_resolve_clockify_export_binary()}")
39
+ (target_dir / "clockify-export.service").write_text(service_source, encoding="utf-8")
40
+ (target_dir / "clockify-export.timer").write_text(
41
+ (bundled_dir / "clockify-export.timer").read_text(encoding="utf-8"),
42
+ encoding="utf-8",
43
+ )
44
+
45
+ for command in (
46
+ ["systemctl", "--user", "daemon-reload"],
47
+ ["systemctl", "--user", "enable", "--now", "clockify-export.timer"],
48
+ ):
49
+ try:
50
+ subprocess.run(command, check=True, capture_output=True, text=True)
51
+ except (FileNotFoundError, subprocess.CalledProcessError) as exc:
52
+ print(f"Warning: unable to run {' '.join(command)}: {exc}", file=sys.stderr)
53
+
54
+ print(f"Installed systemd user units in {target_dir}")
55
+ print("Use: systemctl --user status clockify-export.timer")
@@ -83,6 +83,19 @@ class TestCLI:
83
83
  assert any(f.name == "clockify-export.service" for f in installed_files)
84
84
  assert any(f.name == "clockify-export.timer" for f in installed_files)
85
85
 
86
+ def test_install_systemd_uses_resolved_cli_path(self, tmp_path):
87
+ with isolated_env(tmp_path):
88
+ expected_dir = tmp_path / ".config" / "systemd" / "user"
89
+ resolved = tmp_path / "custom-bin" / "clockify-export"
90
+ resolved.parent.mkdir(parents=True)
91
+ with patch("clockify_export.systemd_install.shutil.which", return_value=str(resolved)):
92
+ with patch("clockify_export.systemd_install.subprocess.run"):
93
+ run_main(["--install-systemd"])
94
+
95
+ service_file = expected_dir / "clockify-export.service"
96
+ content = service_file.read_text(encoding="utf-8")
97
+ assert f"ExecStart={resolved}" in content
98
+
86
99
  def test_missing_api_key_exits(self, capsys, tmp_path):
87
100
  with isolated_env(tmp_path) as config_dir:
88
101
  with patch("clockify_export.config.CONFIG_DIR", config_dir):
@@ -4,7 +4,7 @@ requires-python = ">=3.11"
4
4
 
5
5
  [[package]]
6
6
  name = "clockify-export"
7
- version = "0.3.0"
7
+ version = "0.3.1"
8
8
  source = { editable = "." }
9
9
 
10
10
  [package.optional-dependencies]
@@ -1,30 +0,0 @@
1
- """Helpers for installing the daily systemd timer for clockify-export."""
2
-
3
- from __future__ import annotations
4
-
5
- import subprocess
6
- import sys
7
- from pathlib import Path
8
-
9
-
10
- def install_systemd_user_units() -> None:
11
- """Install the user systemd timer and service for daily exports."""
12
- target_dir = Path.home() / ".config" / "systemd" / "user"
13
- target_dir.mkdir(parents=True, exist_ok=True)
14
-
15
- bundled_dir = Path(__file__).resolve().parent / "systemd"
16
- for target_name in ("clockify-export.service", "clockify-export.timer"):
17
- source = bundled_dir / target_name
18
- (target_dir / target_name).write_text(source.read_text(encoding="utf-8"), encoding="utf-8")
19
-
20
- for command in (
21
- ["systemctl", "--user", "daemon-reload"],
22
- ["systemctl", "--user", "enable", "--now", "clockify-export.timer"],
23
- ):
24
- try:
25
- subprocess.run(command, check=True, capture_output=True, text=True)
26
- except (FileNotFoundError, subprocess.CalledProcessError) as exc:
27
- print(f"Warning: unable to run {' '.join(command)}: {exc}", file=sys.stderr)
28
-
29
- print(f"Installed systemd user units in {target_dir}")
30
- print("Use: systemctl --user status clockify-export.timer")
File without changes
File without changes