mac-upkeep 3.0.2__tar.gz → 3.0.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.
Files changed (39) hide show
  1. mac_upkeep-3.0.3/.release-please-manifest.json +3 -0
  2. {mac_upkeep-3.0.2 → mac_upkeep-3.0.3}/CHANGELOG.md +7 -0
  3. {mac_upkeep-3.0.2 → mac_upkeep-3.0.3}/PKG-INFO +1 -1
  4. {mac_upkeep-3.0.2 → mac_upkeep-3.0.3}/pyproject.toml +1 -1
  5. {mac_upkeep-3.0.2 → mac_upkeep-3.0.3}/src/mac_upkeep/output.py +11 -4
  6. {mac_upkeep-3.0.2 → mac_upkeep-3.0.3}/tests/test_output.py +43 -0
  7. {mac_upkeep-3.0.2 → mac_upkeep-3.0.3}/uv.lock +1 -1
  8. mac_upkeep-3.0.2/.release-please-manifest.json +0 -3
  9. {mac_upkeep-3.0.2 → mac_upkeep-3.0.3}/.github/workflows/release.yml +0 -0
  10. {mac_upkeep-3.0.2 → mac_upkeep-3.0.3}/.github/workflows/test.yml +0 -0
  11. {mac_upkeep-3.0.2 → mac_upkeep-3.0.3}/.gitignore +0 -0
  12. {mac_upkeep-3.0.2 → mac_upkeep-3.0.3}/CLAUDE.md +0 -0
  13. {mac_upkeep-3.0.2 → mac_upkeep-3.0.3}/CONTRIBUTING.md +0 -0
  14. {mac_upkeep-3.0.2 → mac_upkeep-3.0.3}/LICENSE +0 -0
  15. {mac_upkeep-3.0.2 → mac_upkeep-3.0.3}/README.md +0 -0
  16. {mac_upkeep-3.0.2 → mac_upkeep-3.0.3}/demo/demo.gif +0 -0
  17. {mac_upkeep-3.0.2 → mac_upkeep-3.0.3}/demo/record.sh +0 -0
  18. {mac_upkeep-3.0.2 → mac_upkeep-3.0.3}/docs/reusable-patterns.md +0 -0
  19. {mac_upkeep-3.0.2 → mac_upkeep-3.0.3}/llms.txt +0 -0
  20. {mac_upkeep-3.0.2 → mac_upkeep-3.0.3}/release-please-config.json +0 -0
  21. {mac_upkeep-3.0.2 → mac_upkeep-3.0.3}/src/mac_upkeep/__init__.py +0 -0
  22. {mac_upkeep-3.0.2 → mac_upkeep-3.0.3}/src/mac_upkeep/cli.py +0 -0
  23. {mac_upkeep-3.0.2 → mac_upkeep-3.0.3}/src/mac_upkeep/config.py +0 -0
  24. {mac_upkeep-3.0.2 → mac_upkeep-3.0.3}/src/mac_upkeep/defaults.toml +0 -0
  25. {mac_upkeep-3.0.2 → mac_upkeep-3.0.3}/src/mac_upkeep/editor_cache.py +0 -0
  26. {mac_upkeep-3.0.2 → mac_upkeep-3.0.3}/src/mac_upkeep/git_sync.py +0 -0
  27. {mac_upkeep-3.0.2 → mac_upkeep-3.0.3}/src/mac_upkeep/notify.py +0 -0
  28. {mac_upkeep-3.0.2 → mac_upkeep-3.0.3}/src/mac_upkeep/py.typed +0 -0
  29. {mac_upkeep-3.0.2 → mac_upkeep-3.0.3}/src/mac_upkeep/tasks.py +0 -0
  30. {mac_upkeep-3.0.2 → mac_upkeep-3.0.3}/tests/__init__.py +0 -0
  31. {mac_upkeep-3.0.2 → mac_upkeep-3.0.3}/tests/conftest.py +0 -0
  32. {mac_upkeep-3.0.2 → mac_upkeep-3.0.3}/tests/test_cli.py +0 -0
  33. {mac_upkeep-3.0.2 → mac_upkeep-3.0.3}/tests/test_config.py +0 -0
  34. {mac_upkeep-3.0.2 → mac_upkeep-3.0.3}/tests/test_editor_cache.py +0 -0
  35. {mac_upkeep-3.0.2 → mac_upkeep-3.0.3}/tests/test_git_sync.py +0 -0
  36. {mac_upkeep-3.0.2 → mac_upkeep-3.0.3}/tests/test_isolation.py +0 -0
  37. {mac_upkeep-3.0.2 → mac_upkeep-3.0.3}/tests/test_notify.py +0 -0
  38. {mac_upkeep-3.0.2 → mac_upkeep-3.0.3}/tests/test_retry_backoff.py +0 -0
  39. {mac_upkeep-3.0.2 → mac_upkeep-3.0.3}/tests/test_tasks.py +0 -0
@@ -0,0 +1,3 @@
1
+ {
2
+ ".": "3.0.3"
3
+ }
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [3.0.3](https://github.com/calvindotsg/mac-upkeep/compare/v3.0.2...v3.0.3) (2026-08-17)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * report handler tasks as dry-run instead of as having executed ([#51](https://github.com/calvindotsg/mac-upkeep/issues/51)) ([1db8054](https://github.com/calvindotsg/mac-upkeep/commit/1db8054d65da313f6fe4d51f00932d126fc59c79))
9
+
3
10
  ## [3.0.2](https://github.com/calvindotsg/mac-upkeep/compare/v3.0.1...v3.0.2) (2026-08-16)
4
11
 
5
12
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: mac-upkeep
3
- Version: 3.0.2
3
+ Version: 3.0.3
4
4
  Summary: Automated macOS maintenance CLI
5
5
  Project-URL: Homepage, https://github.com/calvindotsg/mac-upkeep
6
6
  Project-URL: Repository, https://github.com/calvindotsg/mac-upkeep
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "mac-upkeep"
3
- version = "3.0.2"
3
+ version = "3.0.3"
4
4
  description = "Automated macOS maintenance CLI"
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -97,9 +97,9 @@ class Output:
97
97
  if t.status == "running":
98
98
  icon = Spinner("dots", style="yellow")
99
99
  detail = Text("running", style="yellow")
100
- elif t.status == "ok" and t.reason == "dry-run":
100
+ elif t.status == "ok" and t.reason.startswith("dry-run"):
101
101
  icon = Text(_DRY, style="cyan")
102
- detail = Text("dry-run", style="dim")
102
+ detail = Text(t.reason, style="dim")
103
103
  elif t.status == "ok":
104
104
  icon = Text(_OK, style="green")
105
105
  detail = Text(f"{t.duration:.1f}s", style="dim") if t.duration else Text("")
@@ -138,8 +138,15 @@ class Output:
138
138
  else:
139
139
  if result.status == "skipped":
140
140
  logger.info("SKIP: %s (%s)", result.name, result.reason)
141
- elif result.status == "ok" and result.reason == "dry-run":
142
- logger.info("DRY-RUN: would run %s", result.name)
141
+ elif result.status == "ok" and result.reason.startswith("dry-run"):
142
+ # Handlers return a richer reason ("dry-run: 17 repos"); command
143
+ # tasks return the bare "dry-run". Surface the extra detail when
144
+ # there is any, so a handler preview is not reduced to a stub.
145
+ detail = result.reason[len("dry-run") :].lstrip(": ")
146
+ if detail:
147
+ logger.info("DRY-RUN: would run %s (%s)", result.name, detail)
148
+ else:
149
+ logger.info("DRY-RUN: would run %s", result.name)
143
150
  elif result.status == "ok":
144
151
  logger.info("Running %s... done", result.name)
145
152
  elif result.status == "failed":
@@ -69,6 +69,49 @@ def test_output_non_interactive_task_done_dry_run(caplog):
69
69
  assert "DRY-RUN" in caplog.text
70
70
 
71
71
 
72
+ def test_output_non_interactive_task_done_dry_run_handler_reason(caplog):
73
+ """Handler tasks return 'dry-run: <detail>', not the bare 'dry-run'.
74
+
75
+ An exact-equality check fell through to the 'Running X... done' branch, so a
76
+ dry run reported handler tasks as if they had executed.
77
+ """
78
+ import logging
79
+
80
+ output = _non_interactive()
81
+ result = TaskResult("git_sync", "ok", reason="dry-run: 17 repos")
82
+ with caplog.at_level(logging.INFO, logger="mac_upkeep"):
83
+ output.task_done(result)
84
+ assert "DRY-RUN: would run git_sync (17 repos)" in caplog.text
85
+ assert "done" not in caplog.text
86
+
87
+
88
+ def test_output_non_interactive_task_done_dry_run_bare_has_no_empty_detail(caplog):
89
+ """The bare 'dry-run' reason must not render an empty '()' suffix."""
90
+ import logging
91
+
92
+ output = _non_interactive()
93
+ result = TaskResult("gcloud", "ok", reason="dry-run")
94
+ with caplog.at_level(logging.INFO, logger="mac_upkeep"):
95
+ output.task_done(result)
96
+ assert "DRY-RUN: would run gcloud" in caplog.text
97
+ assert "()" not in caplog.text
98
+
99
+
100
+ def test_output_non_interactive_ok_reason_is_not_treated_as_dry_run(caplog):
101
+ """A successful handler reason must still read as a real run.
102
+
103
+ Guards the prefix check against over-matching: only 'dry-run...' is a preview.
104
+ """
105
+ import logging
106
+
107
+ output = _non_interactive()
108
+ result = TaskResult("editor_cache", "ok", reason="nothing to clean")
109
+ with caplog.at_level(logging.INFO, logger="mac_upkeep"):
110
+ output.task_done(result)
111
+ assert "Running editor_cache... done" in caplog.text
112
+ assert "DRY-RUN" not in caplog.text
113
+
114
+
72
115
  def test_output_non_interactive_task_done_skipped(caplog):
73
116
  import logging
74
117
 
@@ -43,7 +43,7 @@ wheels = [
43
43
 
44
44
  [[package]]
45
45
  name = "mac-upkeep"
46
- version = "3.0.2"
46
+ version = "3.0.3"
47
47
  source = { editable = "." }
48
48
  dependencies = [
49
49
  { name = "typer" },
@@ -1,3 +0,0 @@
1
- {
2
- ".": "3.0.2"
3
- }
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes