or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

cli.mdconfiguration.mderror-handling.mdindex.mdtask-composition.mdtask-execution.mdvariables.md

task-execution.mddocs/

0

# Task Execution

1

2

Core task execution engine that handles task discovery, execution, pre/post hooks, and process management with comprehensive signal handling.

3

4

## Capabilities

5

6

### TaskRunner Class

7

8

The central class for managing and executing tasks within a project directory.

9

10

```python { .api }

11

class TaskRunner:

12

def __init__(self, cwd: Union[str, Path]):

13

"""

14

Initialize TaskRunner with working directory.

15

16

Args:

17

cwd: Working directory path (str or Path object)

18

"""

19

```

20

21

### Task Listing

22

23

Display available tasks with descriptions and commands in a formatted output.

24

25

```python { .api }

26

def list(self):

27

"""

28

Lists tasks to stdout.

29

30

Displays all available tasks with their names and descriptions

31

(or commands if no description provided) in a formatted table.

32

"""

33

```

34

35

### Task Execution

36

37

Execute a named task with optional arguments, including pre/post hook processing.

38

39

```python { .api }

40

def run(self, task_name: str, args: List[str]) -> int:

41

"""

42

Execute a task with optional arguments.

43

44

Args:

45

task_name: Name of the task to run

46

args: Arguments to pass to the task command

47

48

Returns:

49

Exit code (0 for success, >0 for error)

50

"""

51

```

52

53

## Usage Examples

54

55

### Basic Task Execution

56

57

```python

58

from taskipy.task_runner import TaskRunner

59

from pathlib import Path

60

61

# Initialize runner

62

runner = TaskRunner(Path('/path/to/project'))

63

64

# List available tasks

65

runner.list()

66

67

# Run a task

68

exit_code = runner.run('test', [])

69

70

# Run a task with arguments

71

exit_code = runner.run('test', ['--verbose', '--failfast'])

72

```

73

74

### Error Handling

75

76

```python

77

from taskipy.task_runner import TaskRunner

78

from taskipy.exceptions import TaskNotFoundError, TaskipyError

79

80

runner = TaskRunner(Path('.'))

81

82

try:

83

exit_code = runner.run('nonexistent_task', [])

84

except TaskNotFoundError as e:

85

print(f"Task not found: {e}")

86

if e.suggestion:

87

print(f"Did you mean: {e.suggestion}")

88

except TaskipyError as e:

89

print(f"Taskipy error: {e}")

90

exit_code = e.exit_code

91

```

92

93

### Working with Different Project Structures

94

95

```python

96

# Multi-project repository

97

runner = TaskRunner(Path('/path/to/monorepo/subproject'))

98

99

# Project with custom pyproject.toml location

100

# TaskRunner automatically searches parent directories for pyproject.toml

101

runner = TaskRunner(Path('/path/to/nested/directory'))

102

```

103

104

## Pre and Post Hooks

105

106

TaskRunner automatically executes pre and post hooks for tasks:

107

108

### Hook Execution Order

109

110

1. **Pre-hook**: `pre_{task_name}` (if exists)

111

2. **Main task**: `{task_name}`

112

3. **Post-hook**: `post_{task_name}` (if exists)

113

114

### Hook Behavior

115

116

- If pre-hook fails (non-zero exit code), main task and post-hook are not executed

117

- If main task fails, post-hook is not executed

118

- If main task succeeds but post-hook fails, overall execution returns post-hook's exit code

119

120

### Example Configuration

121

122

```toml

123

[tool.taskipy.tasks]

124

pre_test = "echo 'Setting up test environment'"

125

test = "python -m pytest"

126

post_test = "echo 'Cleaning up test artifacts'"

127

128

pre_lint = "echo 'Preparing linting'"

129

lint = "pylint src tests"

130

post_lint = "echo 'Linting complete'"

131

```

132

133

## Variable Substitution

134

135

TaskRunner handles variable substitution in task commands when enabled:

136

137

```python

138

# Variables are resolved before command execution

139

# Example with variables enabled:

140

# Task: "pylint {src_path}"

141

# Variables: {"src_path": "src/mypackage"}

142

# Executed: "pylint src/mypackage"

143

```

144

145

## Process Management

146

147

### Signal Handling

148

149

TaskRunner provides intelligent process management with proper signal handling:

150

151

- **SIGTERM**: Gracefully terminates child processes

152

- **SIGINT** (Ctrl+C): Handles keyboard interrupts appropriately

153

- **Cross-platform**: Different behavior on macOS vs Linux for shell process handling

154

155

### Working Directory Management

156

157

- Tasks can specify custom working directories via `cwd` parameter

158

- Global `cwd` setting applies to all tasks

159

- Per-task `cwd` overrides global setting

160

- Paths are resolved relative to pyproject.toml location

161

162

### Command Execution

163

164

```python

165

# Commands are executed through shell with proper argument quoting

166

# Example: task test --verbose "with spaces"

167

# Becomes: python -m pytest --verbose "with spaces"

168

```

169

170

## Advanced Features

171

172

### Custom Runners

173

174

TaskRunner supports custom command runners that prefix all task executions:

175

176

```toml

177

[tool.taskipy.settings]

178

runner = "poetry run"

179

```

180

181

This prefixes all task commands with the runner, useful for:

182

- Virtual environment activation

183

- Environment variable loading (e.g., `dotenv run`)

184

- Remote execution (e.g., `ssh server`)

185

186

### Argument Passing

187

188

Arguments passed to tasks are properly quoted and appended to the task command:

189

190

```python

191

# runner.run('test', ['--verbose', '--output-file', 'results.xml'])

192

# Executes: python -m pytest --verbose --output-file results.xml

193

```

194

195

Note: Arguments are only passed to the main task, not to pre/post hooks.

196

197

### Task Suggestions

198

199

When a task is not found, TaskRunner provides intelligent suggestions using difflib:

200

201

```python

202

# If user types 'tets' instead of 'test'

203

# TaskNotFoundError will include suggestion: "did you mean 'test'?"

204

```

205

206

## Process Architecture

207

208

TaskRunner creates subprocess with:

209

- **Shell execution**: Commands run through system shell

210

- **Working directory**: Configurable per task or globally

211

- **Signal forwarding**: Proper signal handling to child processes

212

- **Exit code propagation**: Task exit codes are preserved and returned