or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

cli-parsing.mdcollections.mdconfiguration.mdindex.mdsubprocess-runners.mdtask-execution.mdwatchers.md

subprocess-runners.mddocs/

0

# Subprocess Command Execution

1

2

Invoke provides powerful subprocess execution capabilities through contexts and runners, with support for various execution strategies, output capture, error handling, and interactive features.

3

4

## Capabilities

5

6

### Top-level Convenience Functions

7

8

Simple command execution functions for common use cases.

9

10

```python { .api }

11

def run(command: str, **kwargs):

12

"""

13

Run command in a subprocess and return a Result object.

14

15

This is a convenience wrapper around Context().run().

16

17

Parameters:

18

- command (str): Shell command to execute

19

- **kwargs: Additional execution options (see Context.run)

20

21

Returns:

22

Result: Command execution result

23

"""

24

25

def sudo(command: str, **kwargs):

26

"""

27

Run command in a sudo subprocess and return a Result object.

28

29

This is a convenience wrapper around Context().sudo().

30

31

Parameters:

32

- command (str): Shell command to execute with sudo

33

- **kwargs: Additional execution options (see Context.sudo)

34

35

Returns:

36

Result: Command execution result

37

"""

38

```

39

40

Usage example:

41

42

```python

43

from invoke import run, sudo

44

45

# Basic command execution

46

result = run("ls -la")

47

print(result.stdout)

48

49

# Sudo execution

50

result = sudo("systemctl restart nginx", pty=True)

51

```

52

53

### Context Class

54

55

Main execution context providing subprocess management and configuration.

56

57

```python { .api }

58

class Context:

59

"""

60

Execution context providing command running and configuration management.

61

62

Attributes:

63

- config (Config): Configuration object

64

- cwd (str): Current working directory

65

"""

66

67

def __init__(self, config=None):

68

"""

69

Initialize Context.

70

71

Parameters:

72

- config (Config, optional): Configuration object

73

"""

74

75

def run(self, command, **kwargs):

76

"""

77

Execute a shell command via the configured runner.

78

79

Parameters:

80

- command (str): Shell command to execute

81

- asynchronous (bool): Execute in background and return Promise

82

- disown (bool): Fully detach subprocess (implies asynchronous=True)

83

- echo (bool): Print command before execution

84

- encoding (str): Text encoding for I/O streams

85

- env (dict): Environment variables

86

- err_stream (file-like): Stream for stderr output

87

- hide (bool/str): Hide stdout/stderr ('stdout', 'stderr', 'both', True)

88

- in_stream (file-like): Stream for stdin input

89

- out_stream (file-like): Stream for stdout output

90

- pty (bool): Use a pseudo-terminal

91

- replace_env (bool): Replace entire environment vs updating

92

- shell (str): Shell to use for execution

93

- timeout (float): Command timeout in seconds

94

- warn (bool): Don't raise exceptions on non-zero exit

95

- watchers (list): Stream watchers for interaction

96

97

Returns:

98

Result or Promise: Command execution result

99

"""

100

101

def sudo(self, command, **kwargs):

102

"""

103

Execute a shell command via sudo.

104

105

Parameters:

106

- command (str): Command to execute with sudo

107

- password (str): Sudo password (will prompt if not provided)

108

- user (str): User to sudo as (default: root)

109

- **kwargs: Additional options (same as run())

110

111

Returns:

112

Result or Promise: Command execution result

113

"""

114

115

def cd(self, path):

116

"""

117

Context manager for temporarily changing working directory.

118

119

Parameters:

120

- path (str): Directory path to change to

121

122

Returns:

123

context manager: Directory change context

124

"""

125

126

def prefix(self, command):

127

"""

128

Context manager for prefixing commands.

129

130

Parameters:

131

- command (str): Command prefix to apply

132

133

Returns:

134

context manager: Command prefix context

135

"""

136

```

137

138

### MockContext Class

139

140

Testing mock context for simulating command execution.

141

142

```python { .api }

143

class MockContext(Context):

144

"""

145

Mock context for testing, allowing predefined command results.

146

147

Attributes:

148

- config (Config): Configuration object

149

"""

150

151

def set_result_for(self, command, result):

152

"""

153

Set expected result for a command.

154

155

Parameters:

156

- command (str): Command string to mock

157

- result (Result): Result to return

158

"""

159

```

160

161

### Runner Classes

162

163

Pluggable command execution strategies.

164

165

```python { .api }

166

class Runner:

167

"""

168

Abstract base class for command runners.

169

170

Attributes:

171

- context (Context): Associated context

172

- shell (str): Shell to use for execution

173

- echo (bool): Whether to echo commands

174

- encoding (str): Text encoding for streams

175

"""

176

177

def run(self, command, **kwargs):

178

"""

179

Execute command and return result.

180

181

Parameters:

182

- command (str): Command to execute

183

- **kwargs: Execution options

184

185

Returns:

186

Result: Execution result

187

"""

188

189

class Local(Runner):

190

"""

191

Local subprocess command runner.

192

193

Executes commands on the local machine using subprocess.Popen.

194

"""

195

196

def start(self, command, shell, env):

197

"""

198

Start subprocess for command execution.

199

200

Parameters:

201

- command (str): Command to execute

202

- shell (str): Shell to use

203

- env (dict): Environment variables

204

205

Returns:

206

subprocess.Popen: Started subprocess

207

"""

208

209

def wait(self):

210

"""

211

Wait for subprocess completion.

212

213

Returns:

214

int: Process return code

215

"""

216

```

217

218

### Result Classes

219

220

Command execution results and promises.

221

222

```python { .api }

223

class Result:

224

"""

225

Command execution result.

226

227

Attributes:

228

- return_code (int): Command exit code

229

- stdout (str): Standard output

230

- stderr (str): Standard error

231

- ok (bool): True if return_code == 0

232

- failed (bool): True if return_code != 0

233

- shell (str): Shell used for execution

234

- command (str): Executed command

235

- encoding (str): Text encoding used

236

"""

237

238

def __init__(self, stdout="", stderr="", encoding=None, command="", shell="", return_code=0, pty=False):

239

"""

240

Initialize Result.

241

242

Parameters:

243

- stdout (str): Standard output

244

- stderr (str): Standard error

245

- encoding (str): Text encoding

246

- command (str): Executed command

247

- shell (str): Shell used

248

- return_code (int): Exit code

249

- pty (bool): Whether PTY was used

250

"""

251

252

def tail(self, stream, count=10):

253

"""

254

Get last N lines from output stream.

255

256

Parameters:

257

- stream (str): Stream name ('stdout' or 'stderr')

258

- count (int): Number of lines

259

260

Returns:

261

str: Last N lines

262

"""

263

264

class Promise(Result):

265

"""

266

Asynchronous execution promise.

267

268

Provides access to running subprocess while it executes.

269

"""

270

271

def join(self, timeout=None):

272

"""

273

Wait for subprocess completion.

274

275

Parameters:

276

- timeout (float, optional): Wait timeout

277

278

Returns:

279

Result: Final execution result

280

"""

281

282

def __enter__(self):

283

"""Context manager entry."""

284

return self

285

286

def __exit__(self, *args):

287

"""Context manager exit."""

288

self.join()

289

290

class Failure:

291

"""

292

Command execution failure representation.

293

294

Attributes:

295

- result (Result): Associated result object

296

- reason (str): Failure reason

297

"""

298

```

299

300

## Usage Examples

301

302

### Basic Command Execution

303

304

```python

305

from invoke import Context, run

306

307

# Using convenience function

308

result = run("echo 'Hello World'")

309

print(f"Output: {result.stdout}")

310

print(f"Exit code: {result.return_code}")

311

print(f"Success: {result.ok}")

312

313

# Using context

314

ctx = Context()

315

result = ctx.run("ls -la")

316

if result.failed:

317

print("Command failed!")

318

```

319

320

### Advanced Execution Options

321

322

```python

323

from invoke import Context

324

325

ctx = Context()

326

327

# Hide output

328

result = ctx.run("make build", hide=True)

329

330

# Use PTY for interactive commands

331

result = ctx.run("ssh user@host", pty=True)

332

333

# Set timeout

334

try:

335

result = ctx.run("long-running-command", timeout=30)

336

except CommandTimedOut:

337

print("Command timed out!")

338

339

# Don't raise on failure

340

result = ctx.run("might-fail", warn=True)

341

if result.failed:

342

print(f"Command failed with code {result.return_code}")

343

```

344

345

### Environment and Working Directory

346

347

```python

348

from invoke import Context

349

350

ctx = Context()

351

352

# Set environment variables

353

result = ctx.run("echo $MY_VAR", env={'MY_VAR': 'hello'})

354

355

# Change working directory

356

with ctx.cd('/tmp'):

357

result = ctx.run("pwd") # Shows /tmp

358

359

# Use command prefixes

360

with ctx.prefix('source venv/bin/activate'):

361

result = ctx.run("python --version")

362

```

363

364

### Asynchronous Execution

365

366

```python

367

from invoke import Context

368

369

ctx = Context()

370

371

# Background execution

372

promise = ctx.run("long-task", asynchronous=True)

373

print("Task started, doing other work...")

374

375

# Check if complete

376

if promise.join(timeout=1): # Wait 1 second

377

print("Task completed:", promise.stdout)

378

else:

379

print("Task still running...")

380

381

# Context manager usage

382

with ctx.run("background-task", asynchronous=True) as promise:

383

# Do other work

384

pass

385

# Automatically waits for completion on exit

386

```

387

388

### Error Handling

389

390

```python

391

from invoke import Context, UnexpectedExit

392

393

ctx = Context()

394

395

try:

396

result = ctx.run("false") # Command that returns 1

397

except UnexpectedExit as e:

398

print(f"Command failed: {e.result.return_code}")

399

print(f"Stderr: {e.result.stderr}")

400

401

# Or use warn=True to avoid exceptions

402

result = ctx.run("false", warn=True)

403

if result.failed:

404

print("Command failed but didn't raise exception")

405

```

406

407

### Testing with MockContext

408

409

```python

410

from invoke import MockContext, Result

411

412

# Create mock context

413

ctx = MockContext()

414

415

# Set up expected results

416

ctx.set_result_for("echo hello", Result(stdout="hello\n"))

417

418

# Use in tests

419

result = ctx.run("echo hello")

420

assert result.stdout == "hello\n"

421

```