0
# Task Composition
1
2
Task composition system supporting pre/post hooks, task chaining, and complex workflow orchestration through individual Task objects.
3
4
## Capabilities
5
6
### Task Class
7
8
Individual task representation with metadata and configuration options.
9
10
```python { .api }
11
class Task:
12
def __init__(self, task_name: str, task_toml_contents: object):
13
"""
14
Create Task from TOML configuration.
15
16
Args:
17
task_name: Name of the task
18
task_toml_contents: TOML content (string or dict)
19
"""
20
```
21
22
### Task Properties
23
24
Access to task metadata and configuration.
25
26
```python { .api }
27
@property
28
def name(self) -> str:
29
"""Task name identifier."""
30
31
@property
32
def command(self) -> str:
33
"""Command to execute for this task."""
34
35
@property
36
def description(self) -> str:
37
"""Task description or help text."""
38
39
@property
40
def workdir(self) -> Optional[str]:
41
"""Working directory for task execution."""
42
43
@property
44
def use_vars(self) -> Optional[bool]:
45
"""Whether task uses variable substitution."""
46
```
47
48
## Usage Examples
49
50
### Basic Task Creation
51
52
```python
53
from taskipy.task import Task
54
55
# Create task from string
56
task = Task('test', 'python -m pytest')
57
print(f"Task: {task.name}, Command: {task.command}")
58
59
# Create task from dictionary
60
task_dict = {
61
'cmd': 'python -m pytest',
62
'help': 'Run unit tests',
63
'cwd': 'tests',
64
'use_vars': True
65
}
66
task = Task('test', task_dict)
67
print(f"Description: {task.description}")
68
print(f"Working directory: {task.workdir}")
69
```
70
71
### Task Composition Patterns
72
73
```python
74
# Tasks are automatically composed by TaskRunner based on naming conventions
75
# No direct API needed - composition happens through configuration
76
```
77
78
## Composition Patterns
79
80
### Pre-Task Hooks
81
82
Tasks with names starting with `pre_` automatically run before the main task:
83
84
```toml
85
[tool.taskipy.tasks]
86
pre_test = "echo 'Setting up test environment'"
87
test = "python -m pytest"
88
```
89
90
Execution order: `pre_test` → `test`
91
92
### Post-Task Hooks
93
94
Tasks with names starting with `post_` automatically run after the main task:
95
96
```toml
97
[tool.taskipy.tasks]
98
test = "python -m pytest"
99
post_test = "echo 'Cleaning up test artifacts'"
100
```
101
102
Execution order: `test` → `post_test`
103
104
### Combined Pre/Post Hooks
105
106
Full workflow with setup and cleanup:
107
108
```toml
109
[tool.taskipy.tasks]
110
pre_deploy = "echo 'Building application'"
111
deploy = "rsync -av dist/ server:/var/www/"
112
post_deploy = "echo 'Deployment complete'"
113
```
114
115
Execution order: `pre_deploy` → `deploy` → `post_deploy`
116
117
### Task Chaining
118
119
Chain multiple tasks together using shell operators or task calls:
120
121
```toml
122
[tool.taskipy.tasks]
123
# Using shell operators
124
ci = "task lint && task test && task build"
125
126
# Using task dependencies
127
lint_pylint = "pylint src tests"
128
lint_mypy = "mypy src tests"
129
lint = "task lint_pylint && task lint_mypy"
130
131
# Complex workflows
132
full_check = "task lint && task test && task coverage && task docs"
133
```
134
135
### Conditional Task Execution
136
137
Use shell operators for conditional execution:
138
139
```toml
140
[tool.taskipy.tasks]
141
# Only run tests if lint passes
142
check = "task lint && task test"
143
144
# Run cleanup regardless of test result
145
test_with_cleanup = "task test; task cleanup"
146
147
# Run different commands based on environment
148
deploy = "if [ \"$ENV\" = \"prod\" ]; then task deploy_prod; else task deploy_dev; fi"
149
```
150
151
## Task Configuration Formats
152
153
### Simple String Format
154
155
Direct command specification:
156
157
```toml
158
[tool.taskipy.tasks]
159
test = "python -m pytest"
160
lint = "pylint src tests"
161
build = "python -m build"
162
```
163
164
### Explicit Dictionary Format
165
166
Full configuration with metadata:
167
168
```toml
169
[tool.taskipy.tasks]
170
test = {
171
cmd = "python -m pytest",
172
help = "Run unit tests with pytest",
173
cwd = "tests",
174
use_vars = true
175
}
176
177
lint = {
178
cmd = "pylint {src_path}",
179
help = "Lint code with pylint",
180
use_vars = true
181
}
182
```
183
184
## Working Directory Control
185
186
### Global Working Directory
187
188
Set working directory for all tasks:
189
190
```toml
191
[tool.taskipy.settings]
192
cwd = "src"
193
194
[tool.taskipy.tasks]
195
test = "python -m pytest" # Runs from src/
196
lint = "pylint ." # Runs from src/
197
```
198
199
### Per-Task Working Directory
200
201
Override working directory for specific tasks:
202
203
```toml
204
[tool.taskipy.tasks]
205
test = { cmd = "python -m pytest", cwd = "tests" }
206
lint = { cmd = "pylint .", cwd = "src" }
207
docs = { cmd = "sphinx-build . _build", cwd = "docs" }
208
```
209
210
## Variable Integration
211
212
Tasks can use variable substitution when enabled:
213
214
```toml
215
[tool.taskipy.variables]
216
src_path = "src/mypackage"
217
test_path = "tests"
218
219
[tool.taskipy.tasks]
220
lint = { cmd = "pylint {src_path}", use_vars = true }
221
test = { cmd = "pytest {test_path}", use_vars = true }
222
223
# Or enable globally
224
[tool.taskipy.settings]
225
use_vars = true
226
227
[tool.taskipy.tasks]
228
lint = "pylint {src_path}"
229
test = "pytest {test_path}"
230
```
231
232
## Advanced Composition Examples
233
234
### Build Pipeline
235
236
```toml
237
[tool.taskipy.tasks]
238
# Individual steps
239
clean = "rm -rf dist/ build/"
240
lint = "pylint src tests"
241
test = "python -m pytest"
242
build = "python -m build"
243
upload = "twine upload dist/*"
244
245
# Composed workflows
246
pre_build = "task clean && task lint && task test"
247
build_and_upload = "task build && task upload"
248
full_release = "task pre_build && task build_and_upload"
249
```
250
251
### Development Workflow
252
253
```toml
254
[tool.taskipy.tasks]
255
# Development tasks
256
format = "black src tests"
257
lint = "pylint src tests"
258
type_check = "mypy src"
259
test = "pytest tests/"
260
coverage = "pytest --cov=src tests/"
261
262
# Composed checks
263
check_code = "task format && task lint && task type_check"
264
check_all = "task check_code && task test && task coverage"
265
266
# Pre-commit hook
267
pre_commit = "task check_all"
268
```
269
270
### Environment-Specific Tasks
271
272
```toml
273
[tool.taskipy.tasks]
274
# Base tasks
275
test_unit = "pytest tests/unit"
276
test_integration = "pytest tests/integration"
277
test_e2e = "pytest tests/e2e"
278
279
# Environment compositions
280
test_dev = "task test_unit && task test_integration"
281
test_ci = "task test_unit && task test_integration && task test_e2e"
282
test_all = "task test_ci"
283
```
284
285
## Error Handling in Composition
286
287
### Hook Failure Behavior
288
289
- If pre-hook fails: main task and post-hook are skipped
290
- If main task fails: post-hook is skipped
291
- If main task succeeds but post-hook fails: overall execution fails
292
293
### Robust Composition Patterns
294
295
```toml
296
[tool.taskipy.tasks]
297
# Ensure cleanup runs even if test fails
298
test_with_cleanup = "task test; task cleanup"
299
300
# Continue on lint failure but still run tests
301
flexible_check = "task lint || true; task test"
302
303
# Conditional cleanup based on test result
304
smart_test = "task test && task success_cleanup || task failure_cleanup"
305
```
306
307
## Task Metadata
308
309
### Help Text
310
311
Provide descriptive help for tasks:
312
313
```toml
314
[tool.taskipy.tasks]
315
test = {
316
cmd = "python -m pytest",
317
help = "Run unit tests with coverage reporting"
318
}
319
lint = {
320
cmd = "pylint src tests",
321
help = "Check code style and potential errors"
322
}
323
```
324
325
### Task Documentation
326
327
Use help text to document complex workflows:
328
329
```toml
330
[tool.taskipy.tasks]
331
deploy = {
332
cmd = "task build && task upload && task notify",
333
help = "Full deployment: build, upload to server, notify team"
334
}
335
```