taskpulse-24 0.1.0__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.
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 TaskPulse contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
@@ -0,0 +1,153 @@
1
+ Metadata-Version: 2.4
2
+ Name: taskpulse-24
3
+ Version: 0.1.0
4
+ Summary: A small, dependency-free task prioritizer and daily planner.
5
+ Author: TaskPulse contributors
6
+ License: MIT License
7
+
8
+ Copyright (c) 2026 TaskPulse contributors
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+
28
+
29
+ Project-URL: Homepage, https://github.com/OttoHui/taskpulse
30
+ Project-URL: Repository, https://github.com/OttoHui/taskpulse
31
+ Project-URL: Documentation, https://github.com/OttoHui/taskpulse#readme
32
+ Keywords: productivity,planning,tasks,scheduling
33
+ Classifier: Development Status :: 3 - Alpha
34
+ Classifier: Intended Audience :: Developers
35
+ Classifier: Intended Audience :: Education
36
+ Classifier: License :: OSI Approved :: MIT License
37
+ Classifier: Programming Language :: Python :: 3
38
+ Classifier: Programming Language :: Python :: 3 :: Only
39
+ Requires-Python: >=3.10
40
+ Description-Content-Type: text/markdown
41
+ License-File: LICENSE
42
+ Provides-Extra: dev
43
+ Requires-Dist: pytest>=8; extra == "dev"
44
+ Requires-Dist: ruff>=0.6; extra == "dev"
45
+ Dynamic: license-file
46
+
47
+ # TaskPulse
48
+
49
+ TaskPulse is a small, dependency-free Python package that turns a task list
50
+ into a focused daily plan. It is designed for students and small project teams
51
+ who want transparent prioritization without sending personal data to a service.
52
+
53
+ ## Project team
54
+
55
+ **Group 24 (6/6 members)**
56
+
57
+ - Tsz Hei CHUI
58
+ - Fong Kwan HUI
59
+ - David KWONG
60
+ - Sik Man LAM
61
+ - Hong Shing WONG
62
+ - Chun Hin YIU
63
+
64
+ ## Why it exists
65
+
66
+ Most task apps either require a hosted account or hide prioritization behind a
67
+ complex interface. TaskPulse keeps the algorithm inspectable:
68
+
69
+ 1. importance is explicit (`LOW`, `MEDIUM`, or `HIGH`);
70
+ 2. approaching due dates add urgency;
71
+ 3. shorter tasks win ties, making plans easier to finish;
72
+ 4. tasks are packed into days without splitting a task across sessions.
73
+
74
+ The result is useful for study plans, sprint preparation, and a one-minute
75
+ project demonstration.
76
+
77
+ ## Install
78
+
79
+ ```bash
80
+ pip install taskpulse-24
81
+ ```
82
+
83
+ For local development:
84
+
85
+ ```bash
86
+ git clone https://github.com/OttoHui/taskpulse.git
87
+ cd taskpulse
88
+ pip install -e ".[dev]" # or: pip install -e .
89
+ pytest
90
+ ```
91
+
92
+ ## Python API
93
+
94
+ ```python
95
+ from datetime import date
96
+ from taskpulse import Priority, Task, schedule
97
+
98
+ tasks = [
99
+ Task("Write project abstract", 45, Priority.HIGH, date(2026, 10, 10)),
100
+ Task("Review references", 30, Priority.MEDIUM),
101
+ ]
102
+
103
+ plan = schedule(tasks, daily_minutes=60, start=date(2026, 10, 7))
104
+ for day, items in plan.items():
105
+ print(day, [item.title for item in items])
106
+ ```
107
+
108
+ ## Command line
109
+
110
+ Create `tasks.csv`:
111
+
112
+ ```csv
113
+ title,minutes,priority,due
114
+ Write project abstract,45,3,2026-10-10
115
+ Review references,30,2,
116
+ ```
117
+
118
+ Then run:
119
+
120
+ ```bash
121
+ taskpulse tasks.csv --daily-minutes 60
122
+ ```
123
+
124
+ ## Project and collaboration
125
+
126
+ Suggested team split for Group 24:
127
+
128
+ - **Tsz Hei CHUI:** project coordination, requirements, and final integration.
129
+ - **Fong Kwan HUI:** core models, prioritization, and scheduling logic.
130
+ - **David KWONG:** command-line interface and user experience.
131
+ - **Sik Man LAM:** tests, edge cases, and quality checks.
132
+ - **Hong Shing WONG:** documentation, examples, and PyPI metadata.
133
+ - **Chun Hin YIU:** demo, presentation wiki, and release verification.
134
+
135
+ Make small commits by feature and review each other's pull requests. The
136
+ published distribution is named `taskpulse-24`; its import name remains
137
+ `taskpulse`.
138
+
139
+ ## One-minute demonstration
140
+
141
+ 1. Show the two-row CSV (10 seconds).
142
+ 2. Run `taskpulse tasks.csv --daily-minutes 60` (15 seconds).
143
+ 3. Explain that priority and due date determine order, while capacity determines
144
+ the day (20 seconds).
145
+ 4. Show the equivalent Python API and mention that no external service or
146
+ dependency is required (15 seconds).
147
+
148
+ ## Roadmap
149
+
150
+ - optional weekend skipping;
151
+ - JSON input/output;
152
+ - calendar export;
153
+ - configurable scoring strategies.
@@ -0,0 +1,107 @@
1
+ # TaskPulse
2
+
3
+ TaskPulse is a small, dependency-free Python package that turns a task list
4
+ into a focused daily plan. It is designed for students and small project teams
5
+ who want transparent prioritization without sending personal data to a service.
6
+
7
+ ## Project team
8
+
9
+ **Group 24 (6/6 members)**
10
+
11
+ - Tsz Hei CHUI
12
+ - Fong Kwan HUI
13
+ - David KWONG
14
+ - Sik Man LAM
15
+ - Hong Shing WONG
16
+ - Chun Hin YIU
17
+
18
+ ## Why it exists
19
+
20
+ Most task apps either require a hosted account or hide prioritization behind a
21
+ complex interface. TaskPulse keeps the algorithm inspectable:
22
+
23
+ 1. importance is explicit (`LOW`, `MEDIUM`, or `HIGH`);
24
+ 2. approaching due dates add urgency;
25
+ 3. shorter tasks win ties, making plans easier to finish;
26
+ 4. tasks are packed into days without splitting a task across sessions.
27
+
28
+ The result is useful for study plans, sprint preparation, and a one-minute
29
+ project demonstration.
30
+
31
+ ## Install
32
+
33
+ ```bash
34
+ pip install taskpulse-24
35
+ ```
36
+
37
+ For local development:
38
+
39
+ ```bash
40
+ git clone https://github.com/OttoHui/taskpulse.git
41
+ cd taskpulse
42
+ pip install -e ".[dev]" # or: pip install -e .
43
+ pytest
44
+ ```
45
+
46
+ ## Python API
47
+
48
+ ```python
49
+ from datetime import date
50
+ from taskpulse import Priority, Task, schedule
51
+
52
+ tasks = [
53
+ Task("Write project abstract", 45, Priority.HIGH, date(2026, 10, 10)),
54
+ Task("Review references", 30, Priority.MEDIUM),
55
+ ]
56
+
57
+ plan = schedule(tasks, daily_minutes=60, start=date(2026, 10, 7))
58
+ for day, items in plan.items():
59
+ print(day, [item.title for item in items])
60
+ ```
61
+
62
+ ## Command line
63
+
64
+ Create `tasks.csv`:
65
+
66
+ ```csv
67
+ title,minutes,priority,due
68
+ Write project abstract,45,3,2026-10-10
69
+ Review references,30,2,
70
+ ```
71
+
72
+ Then run:
73
+
74
+ ```bash
75
+ taskpulse tasks.csv --daily-minutes 60
76
+ ```
77
+
78
+ ## Project and collaboration
79
+
80
+ Suggested team split for Group 24:
81
+
82
+ - **Tsz Hei CHUI:** project coordination, requirements, and final integration.
83
+ - **Fong Kwan HUI:** core models, prioritization, and scheduling logic.
84
+ - **David KWONG:** command-line interface and user experience.
85
+ - **Sik Man LAM:** tests, edge cases, and quality checks.
86
+ - **Hong Shing WONG:** documentation, examples, and PyPI metadata.
87
+ - **Chun Hin YIU:** demo, presentation wiki, and release verification.
88
+
89
+ Make small commits by feature and review each other's pull requests. The
90
+ published distribution is named `taskpulse-24`; its import name remains
91
+ `taskpulse`.
92
+
93
+ ## One-minute demonstration
94
+
95
+ 1. Show the two-row CSV (10 seconds).
96
+ 2. Run `taskpulse tasks.csv --daily-minutes 60` (15 seconds).
97
+ 3. Explain that priority and due date determine order, while capacity determines
98
+ the day (20 seconds).
99
+ 4. Show the equivalent Python API and mention that no external service or
100
+ dependency is required (15 seconds).
101
+
102
+ ## Roadmap
103
+
104
+ - optional weekend skipping;
105
+ - JSON input/output;
106
+ - calendar export;
107
+ - configurable scoring strategies.
@@ -0,0 +1,43 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "taskpulse-24"
7
+ version = "0.1.0"
8
+ description = "A small, dependency-free task prioritizer and daily planner."
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = {file = "LICENSE"}
12
+ authors = [{name = "TaskPulse contributors"}]
13
+ keywords = ["productivity", "planning", "tasks", "scheduling"]
14
+ classifiers = [
15
+ "Development Status :: 3 - Alpha",
16
+ "Intended Audience :: Developers",
17
+ "Intended Audience :: Education",
18
+ "License :: OSI Approved :: MIT License",
19
+ "Programming Language :: Python :: 3",
20
+ "Programming Language :: Python :: 3 :: Only",
21
+ ]
22
+
23
+ [project.urls]
24
+ Homepage = "https://github.com/OttoHui/taskpulse"
25
+ Repository = "https://github.com/OttoHui/taskpulse"
26
+ Documentation = "https://github.com/OttoHui/taskpulse#readme"
27
+
28
+ [project.optional-dependencies]
29
+ dev = ["pytest>=8", "ruff>=0.6"]
30
+
31
+ [project.scripts]
32
+ taskpulse = "taskpulse.cli:main"
33
+
34
+ [tool.setuptools.packages.find]
35
+ where = ["src"]
36
+
37
+ [tool.pytest.ini_options]
38
+ testpaths = ["tests"]
39
+ addopts = "-q"
40
+
41
+ [tool.ruff]
42
+ line-length = 88
43
+ target-version = "py310"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,8 @@
1
+ """TaskPulse: turn a task list into a practical daily plan."""
2
+
3
+ from .models import Priority, Task
4
+ from .planner import prioritize, schedule
5
+
6
+ __all__ = ["Priority", "Task", "prioritize", "schedule"]
7
+ __version__ = "0.1.0"
8
+
@@ -0,0 +1,51 @@
1
+ """Command-line interface for quick planning from CSV input."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import argparse
6
+ import csv
7
+ from datetime import date
8
+ from pathlib import Path
9
+
10
+ from .models import Priority, Task
11
+ from .planner import schedule
12
+
13
+
14
+ def _read_tasks(path: Path) -> list[Task]:
15
+ with path.open(newline="", encoding="utf-8") as source:
16
+ rows = csv.DictReader(source)
17
+ required = {"title", "minutes", "priority"}
18
+ if not required.issubset(rows.fieldnames or set()):
19
+ raise ValueError("CSV must contain title, minutes, and priority columns")
20
+ tasks = []
21
+ for row in rows:
22
+ due = date.fromisoformat(row["due"]) if row.get("due") else None
23
+ tasks.append(
24
+ Task(
25
+ title=row["title"],
26
+ minutes=int(row["minutes"]),
27
+ priority=Priority(int(row["priority"])),
28
+ due=due,
29
+ )
30
+ )
31
+ return tasks
32
+
33
+
34
+ def main() -> None:
35
+ parser = argparse.ArgumentParser(description="Build a focused task schedule.")
36
+ parser.add_argument("csv_file", type=Path, help="CSV with title, minutes, priority, due")
37
+ parser.add_argument("--daily-minutes", type=int, default=120)
38
+ args = parser.parse_args()
39
+
40
+ for day, tasks in schedule(
41
+ _read_tasks(args.csv_file),
42
+ daily_minutes=args.daily_minutes,
43
+ ).items():
44
+ print(day.isoformat())
45
+ for task in tasks:
46
+ print(f" - {task.title} ({task.minutes} min, priority {task.priority.name})")
47
+
48
+
49
+ if __name__ == "__main__":
50
+ main()
51
+
@@ -0,0 +1,41 @@
1
+ """Public data models for TaskPulse."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass
6
+ from datetime import date
7
+ from enum import IntEnum
8
+
9
+
10
+ class Priority(IntEnum):
11
+ """User-facing priority levels."""
12
+
13
+ LOW = 1
14
+ MEDIUM = 2
15
+ HIGH = 3
16
+
17
+
18
+ @dataclass(frozen=True, slots=True)
19
+ class Task:
20
+ """A task that can be ranked and scheduled.
21
+
22
+ Args:
23
+ title: Short, human-readable task name.
24
+ minutes: Expected focused work time; must be positive.
25
+ priority: Importance from 1 (low) to 3 (high).
26
+ due: Optional due date. Earlier dates receive more urgency.
27
+ """
28
+
29
+ title: str
30
+ minutes: int
31
+ priority: Priority = Priority.MEDIUM
32
+ due: date | None = None
33
+
34
+ def __post_init__(self) -> None:
35
+ if not self.title.strip():
36
+ raise ValueError("title must not be empty")
37
+ if self.minutes <= 0:
38
+ raise ValueError("minutes must be greater than zero")
39
+ if not isinstance(self.priority, Priority):
40
+ raise TypeError("priority must be a Priority value")
41
+
@@ -0,0 +1,50 @@
1
+ """Task ranking and schedule generation."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from datetime import date, datetime, timedelta
6
+
7
+ from .models import Task
8
+
9
+
10
+ def _score(task: Task, today: date) -> tuple[int, int, int]:
11
+ """Return a sortable score; larger values represent more urgency."""
12
+ due_score = 0 if task.due is None else max(0, 30 - (task.due - today).days)
13
+ return (int(task.priority) * 100 + due_score, -task.minutes, -len(task.title))
14
+
15
+
16
+ def prioritize(tasks: list[Task], *, today: date | None = None) -> list[Task]:
17
+ """Return tasks from most to least urgent without mutating the input."""
18
+ reference = today or datetime.now().astimezone().date()
19
+ return sorted(tasks, key=lambda task: _score(task, reference), reverse=True)
20
+
21
+
22
+ def schedule(
23
+ tasks: list[Task],
24
+ *,
25
+ daily_minutes: int,
26
+ start: date | None = None,
27
+ ) -> dict[date, list[Task]]:
28
+ """Pack prioritized tasks into consecutive workdays.
29
+
30
+ A task is never split. If one task exceeds ``daily_minutes``, it receives
31
+ a day of its own so the function always makes progress.
32
+ """
33
+ if daily_minutes <= 0:
34
+ raise ValueError("daily_minutes must be greater than zero")
35
+
36
+ start_date = start or datetime.now().astimezone().date()
37
+ result: dict[date, list[Task]] = {}
38
+ remaining = daily_minutes
39
+ day = start_date
40
+
41
+ for task in prioritize(tasks, today=start_date):
42
+ if result.get(day) and task.minutes > remaining:
43
+ day += timedelta(days=1)
44
+ remaining = daily_minutes
45
+ result.setdefault(day, []).append(task)
46
+ remaining -= task.minutes
47
+ if remaining <= 0:
48
+ day += timedelta(days=1)
49
+ remaining = daily_minutes
50
+ return result
@@ -0,0 +1,153 @@
1
+ Metadata-Version: 2.4
2
+ Name: taskpulse-24
3
+ Version: 0.1.0
4
+ Summary: A small, dependency-free task prioritizer and daily planner.
5
+ Author: TaskPulse contributors
6
+ License: MIT License
7
+
8
+ Copyright (c) 2026 TaskPulse contributors
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+
28
+
29
+ Project-URL: Homepage, https://github.com/OttoHui/taskpulse
30
+ Project-URL: Repository, https://github.com/OttoHui/taskpulse
31
+ Project-URL: Documentation, https://github.com/OttoHui/taskpulse#readme
32
+ Keywords: productivity,planning,tasks,scheduling
33
+ Classifier: Development Status :: 3 - Alpha
34
+ Classifier: Intended Audience :: Developers
35
+ Classifier: Intended Audience :: Education
36
+ Classifier: License :: OSI Approved :: MIT License
37
+ Classifier: Programming Language :: Python :: 3
38
+ Classifier: Programming Language :: Python :: 3 :: Only
39
+ Requires-Python: >=3.10
40
+ Description-Content-Type: text/markdown
41
+ License-File: LICENSE
42
+ Provides-Extra: dev
43
+ Requires-Dist: pytest>=8; extra == "dev"
44
+ Requires-Dist: ruff>=0.6; extra == "dev"
45
+ Dynamic: license-file
46
+
47
+ # TaskPulse
48
+
49
+ TaskPulse is a small, dependency-free Python package that turns a task list
50
+ into a focused daily plan. It is designed for students and small project teams
51
+ who want transparent prioritization without sending personal data to a service.
52
+
53
+ ## Project team
54
+
55
+ **Group 24 (6/6 members)**
56
+
57
+ - Tsz Hei CHUI
58
+ - Fong Kwan HUI
59
+ - David KWONG
60
+ - Sik Man LAM
61
+ - Hong Shing WONG
62
+ - Chun Hin YIU
63
+
64
+ ## Why it exists
65
+
66
+ Most task apps either require a hosted account or hide prioritization behind a
67
+ complex interface. TaskPulse keeps the algorithm inspectable:
68
+
69
+ 1. importance is explicit (`LOW`, `MEDIUM`, or `HIGH`);
70
+ 2. approaching due dates add urgency;
71
+ 3. shorter tasks win ties, making plans easier to finish;
72
+ 4. tasks are packed into days without splitting a task across sessions.
73
+
74
+ The result is useful for study plans, sprint preparation, and a one-minute
75
+ project demonstration.
76
+
77
+ ## Install
78
+
79
+ ```bash
80
+ pip install taskpulse-24
81
+ ```
82
+
83
+ For local development:
84
+
85
+ ```bash
86
+ git clone https://github.com/OttoHui/taskpulse.git
87
+ cd taskpulse
88
+ pip install -e ".[dev]" # or: pip install -e .
89
+ pytest
90
+ ```
91
+
92
+ ## Python API
93
+
94
+ ```python
95
+ from datetime import date
96
+ from taskpulse import Priority, Task, schedule
97
+
98
+ tasks = [
99
+ Task("Write project abstract", 45, Priority.HIGH, date(2026, 10, 10)),
100
+ Task("Review references", 30, Priority.MEDIUM),
101
+ ]
102
+
103
+ plan = schedule(tasks, daily_minutes=60, start=date(2026, 10, 7))
104
+ for day, items in plan.items():
105
+ print(day, [item.title for item in items])
106
+ ```
107
+
108
+ ## Command line
109
+
110
+ Create `tasks.csv`:
111
+
112
+ ```csv
113
+ title,minutes,priority,due
114
+ Write project abstract,45,3,2026-10-10
115
+ Review references,30,2,
116
+ ```
117
+
118
+ Then run:
119
+
120
+ ```bash
121
+ taskpulse tasks.csv --daily-minutes 60
122
+ ```
123
+
124
+ ## Project and collaboration
125
+
126
+ Suggested team split for Group 24:
127
+
128
+ - **Tsz Hei CHUI:** project coordination, requirements, and final integration.
129
+ - **Fong Kwan HUI:** core models, prioritization, and scheduling logic.
130
+ - **David KWONG:** command-line interface and user experience.
131
+ - **Sik Man LAM:** tests, edge cases, and quality checks.
132
+ - **Hong Shing WONG:** documentation, examples, and PyPI metadata.
133
+ - **Chun Hin YIU:** demo, presentation wiki, and release verification.
134
+
135
+ Make small commits by feature and review each other's pull requests. The
136
+ published distribution is named `taskpulse-24`; its import name remains
137
+ `taskpulse`.
138
+
139
+ ## One-minute demonstration
140
+
141
+ 1. Show the two-row CSV (10 seconds).
142
+ 2. Run `taskpulse tasks.csv --daily-minutes 60` (15 seconds).
143
+ 3. Explain that priority and due date determine order, while capacity determines
144
+ the day (20 seconds).
145
+ 4. Show the equivalent Python API and mention that no external service or
146
+ dependency is required (15 seconds).
147
+
148
+ ## Roadmap
149
+
150
+ - optional weekend skipping;
151
+ - JSON input/output;
152
+ - calendar export;
153
+ - configurable scoring strategies.
@@ -0,0 +1,14 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ src/taskpulse/__init__.py
5
+ src/taskpulse/cli.py
6
+ src/taskpulse/models.py
7
+ src/taskpulse/planner.py
8
+ src/taskpulse_24.egg-info/PKG-INFO
9
+ src/taskpulse_24.egg-info/SOURCES.txt
10
+ src/taskpulse_24.egg-info/dependency_links.txt
11
+ src/taskpulse_24.egg-info/entry_points.txt
12
+ src/taskpulse_24.egg-info/requires.txt
13
+ src/taskpulse_24.egg-info/top_level.txt
14
+ tests/test_planner.py
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ taskpulse = taskpulse.cli:main
@@ -0,0 +1,4 @@
1
+
2
+ [dev]
3
+ pytest>=8
4
+ ruff>=0.6
@@ -0,0 +1,46 @@
1
+ from datetime import date
2
+
3
+ import pytest
4
+
5
+ from taskpulse import Priority, Task, prioritize, schedule
6
+
7
+
8
+ def test_prioritize_prefers_high_priority_and_earlier_due_date():
9
+ today = date(2026, 10, 7)
10
+ later = Task("Later", 30, Priority.HIGH, date(2026, 10, 20))
11
+ sooner = Task("Sooner", 30, Priority.HIGH, date(2026, 10, 8))
12
+ low = Task("Low", 10, Priority.LOW)
13
+
14
+ assert prioritize([low, later, sooner], today=today) == [sooner, later, low]
15
+
16
+
17
+ def test_schedule_packs_tasks_without_splitting():
18
+ start = date(2026, 10, 7)
19
+ tasks = [Task("A", 60, Priority.HIGH), Task("B", 45, Priority.MEDIUM)]
20
+
21
+ plan = schedule(tasks, daily_minutes=60, start=start)
22
+
23
+ assert plan[start] == [tasks[0]]
24
+ assert plan[date(2026, 10, 8)] == [tasks[1]]
25
+
26
+
27
+ def test_oversized_task_gets_a_day_of_its_own():
28
+ start = date(2026, 10, 7)
29
+ task = Task("Long task", 180)
30
+
31
+ assert schedule([task], daily_minutes=120, start=start) == {start: [task]}
32
+
33
+
34
+ @pytest.mark.parametrize(
35
+ "kwargs",
36
+ [{"title": "", "minutes": 10}, {"title": "Task", "minutes": 0}],
37
+ )
38
+ def test_invalid_tasks_are_rejected(kwargs):
39
+ with pytest.raises(ValueError):
40
+ Task(**kwargs)
41
+
42
+
43
+ def test_invalid_daily_capacity_is_rejected():
44
+ with pytest.raises(ValueError, match="daily_minutes"):
45
+ schedule([], daily_minutes=0)
46
+