taskcheck 1.5.0__tar.gz → 1.5.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 (31) hide show
  1. {taskcheck-1.5.0/taskcheck.egg-info → taskcheck-1.5.1}/PKG-INFO +5 -3
  2. {taskcheck-1.5.0 → taskcheck-1.5.1}/README.md +4 -2
  3. {taskcheck-1.5.0 → taskcheck-1.5.1}/pyproject.toml +1 -1
  4. {taskcheck-1.5.0 → taskcheck-1.5.1}/taskcheck/__main__.py +7 -3
  5. taskcheck-1.5.1/taskcheck/dry_run.py +22 -0
  6. {taskcheck-1.5.0 → taskcheck-1.5.1/taskcheck.egg-info}/PKG-INFO +5 -3
  7. {taskcheck-1.5.0 → taskcheck-1.5.1}/taskcheck.egg-info/SOURCES.txt +1 -0
  8. {taskcheck-1.5.0 → taskcheck-1.5.1}/tests/test_main.py +44 -1
  9. {taskcheck-1.5.0 → taskcheck-1.5.1}/LICENSE +0 -0
  10. {taskcheck-1.5.0 → taskcheck-1.5.1}/setup.cfg +0 -0
  11. {taskcheck-1.5.0 → taskcheck-1.5.1}/taskcheck/common.py +0 -0
  12. {taskcheck-1.5.0 → taskcheck-1.5.1}/taskcheck/google_calendar.py +0 -0
  13. {taskcheck-1.5.0 → taskcheck-1.5.1}/taskcheck/ical.py +0 -0
  14. {taskcheck-1.5.0 → taskcheck-1.5.1}/taskcheck/install.py +0 -0
  15. {taskcheck-1.5.0 → taskcheck-1.5.1}/taskcheck/parallel.py +0 -0
  16. {taskcheck-1.5.0 → taskcheck-1.5.1}/taskcheck/report.py +0 -0
  17. {taskcheck-1.5.0 → taskcheck-1.5.1}/taskcheck/theme.py +0 -0
  18. {taskcheck-1.5.0 → taskcheck-1.5.1}/taskcheck/timeline.py +0 -0
  19. {taskcheck-1.5.0 → taskcheck-1.5.1}/taskcheck/undo.py +0 -0
  20. {taskcheck-1.5.0 → taskcheck-1.5.1}/taskcheck.egg-info/dependency_links.txt +0 -0
  21. {taskcheck-1.5.0 → taskcheck-1.5.1}/taskcheck.egg-info/entry_points.txt +0 -0
  22. {taskcheck-1.5.0 → taskcheck-1.5.1}/taskcheck.egg-info/requires.txt +0 -0
  23. {taskcheck-1.5.0 → taskcheck-1.5.1}/taskcheck.egg-info/top_level.txt +0 -0
  24. {taskcheck-1.5.0 → taskcheck-1.5.1}/tests/test_common.py +0 -0
  25. {taskcheck-1.5.0 → taskcheck-1.5.1}/tests/test_google_calendar.py +0 -0
  26. {taskcheck-1.5.0 → taskcheck-1.5.1}/tests/test_ical.py +0 -0
  27. {taskcheck-1.5.0 → taskcheck-1.5.1}/tests/test_install.py +0 -0
  28. {taskcheck-1.5.0 → taskcheck-1.5.1}/tests/test_parallel.py +0 -0
  29. {taskcheck-1.5.0 → taskcheck-1.5.1}/tests/test_report.py +0 -0
  30. {taskcheck-1.5.0 → taskcheck-1.5.1}/tests/test_timeline.py +0 -0
  31. {taskcheck-1.5.0 → taskcheck-1.5.1}/tests/test_undo.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: taskcheck
3
- Version: 1.5.0
3
+ Version: 1.5.1
4
4
  Summary: Automatic scheduler for taskwarrior
5
5
  Requires-Python: >=3.11
6
6
  Description-Content-Type: text/markdown
@@ -32,7 +32,7 @@ Use it if you want to:
32
32
  - ✨ Auto-schedule tasks from working hours + calendar blocks
33
33
  - 🧭 Support complex working-hour maps
34
34
  - ⏱️ Consider urgency, due dates, and dependencies
35
- - 🧪 Dry-run mode to preview changes
35
+ - 🧪 Persisted dry-run previews for reports and timelines
36
36
  - ↩️ Undo the latest schedule update
37
37
  - 🧠 Auto-adjust urgency when deadlines cannot be met
38
38
  - 🔄 Force-refresh iCal calendars
@@ -84,7 +84,9 @@ tuesday = [[9, 12.30], [14, 17]]
84
84
  - `taskcheck --timeline 1w` → automatic day/week/month timeline for the next week
85
85
  - `taskcheck --timeline eom --zoom week` → weekly timeline through month end
86
86
 
87
- Timeline rows follow dotted project levels such as `work.client`. Without `--zoom`, the most detailed view that fits the terminal width is selected: day, then week, then month. The track uses `▶` for a start, `━` for work, `◀` for an end, and `◆` for a deadline. Thin, heavy, and double rules separate days, weeks, and months. Project colors are deterministic and adapt to light or dark terminals when `COLORFGBG` is available.
87
+ Create a preview with `taskcheck --schedule --dry-run`. It does not update Taskwarrior; instead, it saves the generated schedule to the Taskwarrior data directory. Reuse it with `taskcheck --report today --dry-run` or `taskcheck --timeline 1w --dry-run`.
88
+
89
+ Timeline rows follow dotted project levels such as `work.client`. Without `--zoom`, the most detailed view that fits the terminal width is selected: day, then week, then month. The track uses `▶` for a start, `━` for work, `◀` for an end, and `◆` for a deadline. Thin, heavy, and double rules separate days, weeks, and months. Project colors are deterministic and adapt to light or dark terminals through OSC 11, with config and environment fallbacks.
88
90
 
89
91
  ## Reference
90
92
 
@@ -17,7 +17,7 @@ Use it if you want to:
17
17
  - ✨ Auto-schedule tasks from working hours + calendar blocks
18
18
  - 🧭 Support complex working-hour maps
19
19
  - ⏱️ Consider urgency, due dates, and dependencies
20
- - 🧪 Dry-run mode to preview changes
20
+ - 🧪 Persisted dry-run previews for reports and timelines
21
21
  - ↩️ Undo the latest schedule update
22
22
  - 🧠 Auto-adjust urgency when deadlines cannot be met
23
23
  - 🔄 Force-refresh iCal calendars
@@ -69,7 +69,9 @@ tuesday = [[9, 12.30], [14, 17]]
69
69
  - `taskcheck --timeline 1w` → automatic day/week/month timeline for the next week
70
70
  - `taskcheck --timeline eom --zoom week` → weekly timeline through month end
71
71
 
72
- Timeline rows follow dotted project levels such as `work.client`. Without `--zoom`, the most detailed view that fits the terminal width is selected: day, then week, then month. The track uses `▶` for a start, `━` for work, `◀` for an end, and `◆` for a deadline. Thin, heavy, and double rules separate days, weeks, and months. Project colors are deterministic and adapt to light or dark terminals when `COLORFGBG` is available.
72
+ Create a preview with `taskcheck --schedule --dry-run`. It does not update Taskwarrior; instead, it saves the generated schedule to the Taskwarrior data directory. Reuse it with `taskcheck --report today --dry-run` or `taskcheck --timeline 1w --dry-run`.
73
+
74
+ Timeline rows follow dotted project levels such as `work.client`. Without `--zoom`, the most detailed view that fits the terminal width is selected: day, then week, then month. The track uses `▶` for a start, `━` for work, `◀` for an end, and `◆` for a deadline. Thin, heavy, and double rules separate days, weeks, and months. Project colors are deterministic and adapt to light or dark terminals through OSC 11, with config and environment fallbacks.
73
75
 
74
76
  ## Reference
75
77
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "taskcheck"
3
- version = "1.5.0"
3
+ version = "1.5.1"
4
4
  description = "Automatic scheduler for taskwarrior"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -4,6 +4,7 @@ from importlib.metadata import version
4
4
 
5
5
  from taskcheck.parallel import check_tasks_parallel
6
6
  from taskcheck.common import config_dir
7
+ from taskcheck.dry_run import load_dry_run_results, save_dry_run_results
7
8
 
8
9
  arg_parser = argparse.ArgumentParser()
9
10
  arg_parser.add_argument("--version", action="version", version=f"taskcheck {version('taskcheck')}")
@@ -151,6 +152,8 @@ def main():
151
152
  config,
152
153
  **check_tasks_kwargs,
153
154
  )
155
+ if args.dry_run and result is not None:
156
+ save_dry_run_results(result, taskrc=args.taskrc)
154
157
  print_help = False
155
158
 
156
159
  if args.report:
@@ -158,9 +161,8 @@ def main():
158
161
 
159
162
  config = load_config()
160
163
  scheduling_results = None
161
- if args.schedule and args.dry_run:
162
- # If we just did a dry-run schedule, use those results
163
- scheduling_results = result
164
+ if args.dry_run:
165
+ scheduling_results = result if args.schedule else load_dry_run_results(args.taskrc)
164
166
  generate_report(
165
167
  config,
166
168
  args.report,
@@ -176,6 +178,8 @@ def main():
176
178
  from taskcheck.timeline import generate_timeline
177
179
 
178
180
  scheduling_results = result if args.schedule and args.dry_run else None
181
+ if args.dry_run and scheduling_results is None:
182
+ scheduling_results = load_dry_run_results(args.taskrc)
179
183
  zoom = getattr(args, "zoom", "day")
180
184
  if zoom not in {"auto", "day", "week", "month"}:
181
185
  zoom = "auto"
@@ -0,0 +1,22 @@
1
+ import json
2
+ from pathlib import Path
3
+
4
+ from taskcheck.undo import get_task_data_dir
5
+
6
+
7
+ def get_dry_run_path(taskrc=None):
8
+ return get_task_data_dir(taskrc) / "taskcheck" / "dry-run.json"
9
+
10
+
11
+ def save_dry_run_results(results, taskrc=None):
12
+ path = get_dry_run_path(taskrc)
13
+ path.parent.mkdir(parents=True, exist_ok=True)
14
+ path.write_text(json.dumps(results, indent=2, sort_keys=True))
15
+ return path
16
+
17
+
18
+ def load_dry_run_results(taskrc=None):
19
+ path = get_dry_run_path(taskrc)
20
+ if not path.exists():
21
+ return None
22
+ return json.loads(path.read_text())
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: taskcheck
3
- Version: 1.5.0
3
+ Version: 1.5.1
4
4
  Summary: Automatic scheduler for taskwarrior
5
5
  Requires-Python: >=3.11
6
6
  Description-Content-Type: text/markdown
@@ -32,7 +32,7 @@ Use it if you want to:
32
32
  - ✨ Auto-schedule tasks from working hours + calendar blocks
33
33
  - 🧭 Support complex working-hour maps
34
34
  - ⏱️ Consider urgency, due dates, and dependencies
35
- - 🧪 Dry-run mode to preview changes
35
+ - 🧪 Persisted dry-run previews for reports and timelines
36
36
  - ↩️ Undo the latest schedule update
37
37
  - 🧠 Auto-adjust urgency when deadlines cannot be met
38
38
  - 🔄 Force-refresh iCal calendars
@@ -84,7 +84,9 @@ tuesday = [[9, 12.30], [14, 17]]
84
84
  - `taskcheck --timeline 1w` → automatic day/week/month timeline for the next week
85
85
  - `taskcheck --timeline eom --zoom week` → weekly timeline through month end
86
86
 
87
- Timeline rows follow dotted project levels such as `work.client`. Without `--zoom`, the most detailed view that fits the terminal width is selected: day, then week, then month. The track uses `▶` for a start, `━` for work, `◀` for an end, and `◆` for a deadline. Thin, heavy, and double rules separate days, weeks, and months. Project colors are deterministic and adapt to light or dark terminals when `COLORFGBG` is available.
87
+ Create a preview with `taskcheck --schedule --dry-run`. It does not update Taskwarrior; instead, it saves the generated schedule to the Taskwarrior data directory. Reuse it with `taskcheck --report today --dry-run` or `taskcheck --timeline 1w --dry-run`.
88
+
89
+ Timeline rows follow dotted project levels such as `work.client`. Without `--zoom`, the most detailed view that fits the terminal width is selected: day, then week, then month. The track uses `▶` for a start, `━` for work, `◀` for an end, and `◆` for a deadline. Thin, heavy, and double rules separate days, weeks, and months. Project colors are deterministic and adapt to light or dark terminals through OSC 11, with config and environment fallbacks.
88
90
 
89
91
  ## Reference
90
92
 
@@ -3,6 +3,7 @@ README.md
3
3
  pyproject.toml
4
4
  taskcheck/__main__.py
5
5
  taskcheck/common.py
6
+ taskcheck/dry_run.py
6
7
  taskcheck/google_calendar.py
7
8
  taskcheck/ical.py
8
9
  taskcheck/install.py
@@ -413,10 +413,11 @@ class TestMainFunction:
413
413
  auto_adjust_urgency=True,
414
414
  )
415
415
 
416
+ @patch("taskcheck.__main__.save_dry_run_results")
416
417
  @patch("taskcheck.__main__.load_config")
417
418
  @patch("taskcheck.__main__.check_tasks_parallel")
418
419
  def test_main_schedule_with_dry_run(
419
- self, mock_check_tasks, mock_load_config, sample_config, test_taskrc
420
+ self, mock_check_tasks, mock_load_config, mock_save, sample_config, test_taskrc
420
421
  ):
421
422
  """Test that dry-run mode returns scheduling results without modifying tasks."""
422
423
  mock_load_config.return_value = sample_config
@@ -437,6 +438,7 @@ class TestMainFunction:
437
438
  }
438
439
  ]
439
440
  mock_check_tasks.return_value = dry_run_results
441
+ mock_save.return_value = None
440
442
 
441
443
  with patch(
442
444
  "sys.argv",
@@ -469,6 +471,7 @@ class TestMainFunction:
469
471
  )
470
472
  mock_load_config.assert_called_once()
471
473
 
474
+ @patch("taskcheck.__main__.save_dry_run_results")
472
475
  @patch("taskcheck.__main__.load_config")
473
476
  @patch("taskcheck.__main__.check_tasks_parallel")
474
477
  @patch("taskcheck.report.generate_report")
@@ -477,6 +480,7 @@ class TestMainFunction:
477
480
  mock_generate_report,
478
481
  mock_check_tasks,
479
482
  mock_load_config,
483
+ mock_save,
480
484
  sample_config,
481
485
  test_taskrc,
482
486
  ):
@@ -499,6 +503,7 @@ class TestMainFunction:
499
503
  }
500
504
  ]
501
505
  mock_check_tasks.return_value = dry_run_results
506
+ mock_save.return_value = None
502
507
 
503
508
  with patch(
504
509
  "sys.argv",
@@ -536,6 +541,7 @@ class TestMainFunction:
536
541
  taskrc=test_taskrc,
537
542
  scheduling_results=dry_run_results,
538
543
  )
544
+ mock_save.assert_called_once_with(dry_run_results, taskrc=test_taskrc)
539
545
 
540
546
  # Verify that check_tasks_parallel was called with dry_run=True
541
547
  mock_check_tasks.assert_called_once_with(
@@ -548,6 +554,43 @@ class TestMainFunction:
548
554
  auto_adjust_urgency=True,
549
555
  )
550
556
 
557
+ @patch("taskcheck.__main__.load_dry_run_results")
558
+ @patch("taskcheck.__main__.load_config")
559
+ @patch("taskcheck.report.generate_report")
560
+ def test_main_report_dry_run_loads_cached_results(
561
+ self, mock_generate_report, mock_load_config, mock_load_cache, sample_config, test_taskrc
562
+ ):
563
+ mock_load_config.return_value = sample_config
564
+ cached = [{"id": "1", "scheduling": "2024-12-20 - PT2H"}]
565
+ mock_load_cache.return_value = cached
566
+
567
+ with patch("sys.argv", ["taskcheck", "--report", "today", "--dry-run", "--taskrc", test_taskrc]):
568
+ with patch("taskcheck.__main__.arg_parser.parse_args") as mock_parse:
569
+ mock_args = Mock()
570
+ mock_args.install = False
571
+ mock_args.schedule = False
572
+ mock_args.report = "today"
573
+ mock_args.timeline = None
574
+ mock_args.zoom = "auto"
575
+ mock_args.verbose = False
576
+ mock_args.force_update = False
577
+ mock_args.taskrc = test_taskrc
578
+ mock_args.urgency_weight = None
579
+ mock_args.dry_run = True
580
+ mock_args.auto_adjust_urgency = True
581
+ mock_parse.return_value = mock_args
582
+ main()
583
+
584
+ mock_load_cache.assert_called_once_with(test_taskrc)
585
+ mock_generate_report.assert_called_once_with(
586
+ sample_config,
587
+ "today",
588
+ False,
589
+ force_update=False,
590
+ taskrc=test_taskrc,
591
+ scheduling_results=cached,
592
+ )
593
+
551
594
  @patch("taskcheck.__main__.load_config")
552
595
  def test_main_config_loading_error(self, mock_load_config):
553
596
  """Test behavior when config loading fails."""
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