or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

aliases.mdapi-package.mdbuiltins-api.mdcompletion.mdconfiguration.mddirectory-management.mdevents.mdindex.mdscripting.mdshell-interface.md

api-package.mddocs/

0

# API Package

1

2

## Overview

3

4

The xonsh.api package provides a pure Python interface to xonsh functionality, designed for use by external tools and scripts that need xonsh capabilities without running a full xonsh shell. This package includes subprocess wrappers and OS utilities that leverage xonsh's enhanced command execution.

5

6

## Subprocess Module

7

8

### Enhanced Subprocess Functions

9

10

```python { .api }

11

from xonsh.api.subprocess import run, check_call, check_output

12

13

def run(cmd: list[str], cwd: str = None, check: bool = False) -> object:

14

"""Drop-in replacement for subprocess.run with xonsh enhancements.

15

16

Parameters

17

----------

18

cmd : list[str]

19

Command and arguments to execute

20

cwd : str, optional

21

Working directory for command execution

22

check : bool, default False

23

Whether to raise exception on non-zero return code

24

25

Returns

26

-------

27

object

28

Process object with stdout, stderr, returncode attributes

29

30

Examples

31

--------

32

# Basic command execution

33

result = run(['ls', '-la'])

34

print(f"Return code: {result.returncode}")

35

36

# With working directory

37

result = run(['git', 'status'], cwd='/path/to/repo')

38

39

# With error checking

40

result = run(['make', 'build'], check=True) # Raises on failure

41

"""

42

43

def check_call(cmd: list[str], cwd: str = None) -> int:

44

"""Execute command and raise exception on failure.

45

46

Parameters

47

----------

48

cmd : list[str]

49

Command and arguments to execute

50

cwd : str, optional

51

Working directory for command execution

52

53

Returns

54

-------

55

int

56

Return code (always 0 if successful)

57

58

Raises

59

------

60

CalledProcessError

61

If command returns non-zero exit code

62

63

Examples

64

--------

65

# Successful command

66

check_call(['mkdir', '-p', '/tmp/test'])

67

68

# Command with working directory

69

check_call(['npm', 'install'], cwd='/path/to/project')

70

71

# Will raise exception if git command fails

72

check_call(['git', 'push', 'origin', 'main'])

73

"""

74

75

def check_output(cmd: list[str], cwd: str = None) -> bytes:

76

"""Execute command and return output, raising exception on failure.

77

78

Parameters

79

----------

80

cmd : list[str]

81

Command and arguments to execute

82

cwd : str, optional

83

Working directory for command execution

84

85

Returns

86

-------

87

bytes

88

Command output as bytes

89

90

Raises

91

------

92

CalledProcessError

93

If command returns non-zero exit code

94

95

Examples

96

--------

97

# Get command output

98

output = check_output(['git', 'rev-parse', 'HEAD'])

99

commit_hash = output.decode().strip()

100

101

# Command with working directory

102

files = check_output(['ls', '-1'], cwd='/tmp')

103

file_list = files.decode().strip().split('\n')

104

105

# Will raise exception if command fails

106

version = check_output(['python', '--version'])

107

"""

108

```

109

110

## OS Module

111

112

### Enhanced OS Utilities

113

114

```python { .api }

115

from xonsh.api.os import rmtree, indir

116

117

def rmtree(dirname: str, force: bool = False) -> None:

118

"""Remove directory tree with cross-platform compatibility.

119

120

Handles read-only files on Windows that standard rmtree cannot remove.

121

Uses xonsh subprocess execution for reliable cross-platform operation.

122

123

Parameters

124

----------

125

dirname : str

126

Directory path to remove

127

force : bool, default False

128

If True, force removal (adds 'f' flag on Unix systems)

129

130

Examples

131

--------

132

# Basic directory removal

133

rmtree('/tmp/test_dir')

134

135

# Force removal (useful for git repositories with read-only files)

136

rmtree('/tmp/repo_clone', force=True)

137

138

# Windows-compatible removal

139

import sys

140

if sys.platform == 'win32':

141

rmtree('C:\\temp\\test') # Uses rmdir /S/Q

142

else:

143

rmtree('/tmp/test') # Uses rm -r

144

"""

145

146

def indir(dirname: str):

147

"""Context manager for temporary directory changes.

148

149

Alias to xonsh.dirstack.with_pushd for API consistency.

150

Changes to specified directory and restores original directory on exit.

151

152

Parameters

153

----------

154

dirname : str

155

Directory to change to temporarily

156

157

Returns

158

-------

159

context manager

160

Context manager for directory change

161

162

Examples

163

--------

164

import os

165

166

# Temporary directory change

167

print(f"Original: {os.getcwd()}")

168

with indir('/tmp'):

169

print(f"Inside context: {os.getcwd()}") # /tmp

170

# Do work in /tmp

171

print(f"Restored: {os.getcwd()}") # Original directory

172

173

# Nested directory changes

174

with indir('/var'):

175

print(f"First level: {os.getcwd()}")

176

with indir('log'):

177

print(f"Nested: {os.getcwd()}") # /var/log

178

print(f"Back to first: {os.getcwd()}") # /var

179

"""

180

181

# Direct alias for convenience

182

from xonsh.dirstack import with_pushd

183

indir = with_pushd # Context manager for directory changes

184

```

185

186

## Integration Patterns

187

188

### Using API in External Scripts

189

190

```python { .api }

191

#!/usr/bin/env python3

192

"""Example external script using xonsh API."""

193

194

from xonsh.api.subprocess import run, check_output

195

from xonsh.api.os import indir, rmtree

196

197

def deploy_project(project_path: str, deploy_path: str) -> bool:

198

"""Deploy project using xonsh API functions.

199

200

Parameters

201

----------

202

project_path : str

203

Source project directory

204

deploy_path : str

205

Deployment target directory

206

207

Returns

208

-------

209

bool

210

True if deployment successful

211

"""

212

try:

213

# Clean deployment directory

214

rmtree(deploy_path, force=True)

215

216

# Build project

217

with indir(project_path):

218

result = run(['npm', 'run', 'build'], check=True)

219

220

# Get build info

221

build_info = check_output(['npm', 'run', 'build:info'])

222

print(f"Build info: {build_info.decode().strip()}")

223

224

# Copy build artifacts

225

result = run(['cp', '-r', f'{project_path}/dist', deploy_path])

226

227

return result.returncode == 0

228

229

except Exception as e:

230

print(f"Deployment failed: {e}")

231

return False

232

233

# Usage

234

if __name__ == '__main__':

235

success = deploy_project('/src/myapp', '/var/www/myapp')

236

print(f"Deployment {'succeeded' if success else 'failed'}")

237

```

238

239

### Library Integration

240

241

```python { .api }

242

"""Library that uses xonsh API for enhanced subprocess operations."""

243

244

from xonsh.api.subprocess import run, check_output

245

from xonsh.api.os import indir

246

import json

247

import os

248

249

class ProjectManager:

250

"""Project management using xonsh API."""

251

252

def __init__(self, project_root: str):

253

"""Initialize project manager.

254

255

Parameters

256

----------

257

project_root : str

258

Root directory of the project

259

"""

260

self.project_root = project_root

261

262

def get_git_info(self) -> dict:

263

"""Get git repository information.

264

265

Returns

266

-------

267

dict

268

Git repository information

269

"""

270

with indir(self.project_root):

271

try:

272

# Get current branch

273

branch = check_output(['git', 'rev-parse', '--abbrev-ref', 'HEAD'])

274

branch = branch.decode().strip()

275

276

# Get commit hash

277

commit = check_output(['git', 'rev-parse', 'HEAD'])

278

commit = commit.decode().strip()

279

280

# Get status

281

status_result = run(['git', 'status', '--porcelain'])

282

is_clean = status_result.returncode == 0 and not status_result.stdout

283

284

return {

285

'branch': branch,

286

'commit': commit,

287

'is_clean': is_clean,

288

'has_git': True

289

}

290

except:

291

return {'has_git': False}

292

293

def run_tests(self) -> bool:

294

"""Run project tests.

295

296

Returns

297

-------

298

bool

299

True if tests pass

300

"""

301

with indir(self.project_root):

302

# Try different test runners

303

test_commands = [

304

['npm', 'test'],

305

['python', '-m', 'pytest'],

306

['python', '-m', 'unittest'],

307

['make', 'test']

308

]

309

310

for cmd in test_commands:

311

if self._command_exists(cmd[0]):

312

result = run(cmd)

313

return result.returncode == 0

314

315

return False

316

317

def _command_exists(self, command: str) -> bool:

318

"""Check if command exists."""

319

result = run(['which', command])

320

return result.returncode == 0

321

322

# Usage example

323

project = ProjectManager('/path/to/project')

324

git_info = project.get_git_info()

325

test_result = project.run_tests()

326

```

327

328

### Configuration and Environment

329

330

```python { .api }

331

"""Configuration utilities using xonsh API."""

332

333

from xonsh.api.subprocess import check_output, run

334

from xonsh.api.os import indir

335

import os

336

import json

337

338

def detect_project_type(project_path: str) -> str:

339

"""Detect project type from files and configuration.

340

341

Parameters

342

----------

343

project_path : str

344

Project directory path

345

346

Returns

347

-------

348

str

349

Project type ('python', 'node', 'go', 'rust', 'unknown')

350

"""

351

with indir(project_path):

352

# Check for specific files

353

if os.path.exists('package.json'):

354

return 'node'

355

elif os.path.exists('pyproject.toml') or os.path.exists('setup.py'):

356

return 'python'

357

elif os.path.exists('go.mod'):

358

return 'go'

359

elif os.path.exists('Cargo.toml'):

360

return 'rust'

361

elif os.path.exists('Makefile'):

362

return 'make'

363

else:

364

return 'unknown'

365

366

def get_project_dependencies(project_path: str) -> dict:

367

"""Get project dependencies using appropriate package manager.

368

369

Parameters

370

----------

371

project_path : str

372

Project directory path

373

374

Returns

375

-------

376

dict

377

Dependencies information

378

"""

379

project_type = detect_project_type(project_path)

380

381

with indir(project_path):

382

if project_type == 'node':

383

try:

384

output = check_output(['npm', 'list', '--json'])

385

return json.loads(output.decode())

386

except:

387

return {}

388

389

elif project_type == 'python':

390

try:

391

# Try pip list

392

output = check_output(['pip', 'list', '--format=json'])

393

packages = json.loads(output.decode())

394

return {pkg['name']: pkg['version'] for pkg in packages}

395

except:

396

return {}

397

398

return {}

399

400

def setup_development_environment(project_path: str) -> bool:

401

"""Setup development environment for project.

402

403

Parameters

404

----------

405

project_path : str

406

Project directory path

407

408

Returns

409

-------

410

bool

411

True if setup successful

412

"""

413

project_type = detect_project_type(project_path)

414

415

with indir(project_path):

416

try:

417

if project_type == 'node':

418

result = run(['npm', 'install'], check=True)

419

return True

420

421

elif project_type == 'python':

422

# Create virtual environment if needed

423

if not os.path.exists('venv'):

424

run(['python', '-m', 'venv', 'venv'], check=True)

425

426

# Install dependencies

427

if os.path.exists('requirements.txt'):

428

run(['venv/bin/pip', 'install', '-r', 'requirements.txt'], check=True)

429

elif os.path.exists('pyproject.toml'):

430

run(['venv/bin/pip', 'install', '-e', '.'], check=True)

431

432

return True

433

434

return False

435

436

except Exception as e:

437

print(f"Setup failed: {e}")

438

return False

439

```

440

441

## Error Handling and Best Practices

442

443

### Robust Error Handling

444

445

```python { .api }

446

from xonsh.api.subprocess import run, check_output

447

from xonsh.api.os import indir

448

import logging

449

450

def safe_command_execution(cmd: list[str], cwd: str = None,

451

timeout: int = 30) -> tuple[bool, str]:

452

"""Safely execute command with comprehensive error handling.

453

454

Parameters

455

----------

456

cmd : list[str]

457

Command to execute

458

cwd : str, optional

459

Working directory

460

timeout : int, default 30

461

Command timeout in seconds

462

463

Returns

464

-------

465

tuple[bool, str]

466

(success, output_or_error_message)

467

"""

468

try:

469

if cwd:

470

with indir(cwd):

471

result = run(cmd, check=False)

472

else:

473

result = run(cmd, check=False)

474

475

if result.returncode == 0:

476

output = result.stdout if hasattr(result, 'stdout') else ""

477

return True, output

478

else:

479

error = result.stderr if hasattr(result, 'stderr') else f"Command failed with code {result.returncode}"

480

return False, error

481

482

except FileNotFoundError:

483

return False, f"Command '{cmd[0]}' not found"

484

except PermissionError:

485

return False, f"Permission denied executing '{cmd[0]}'"

486

except Exception as e:

487

return False, f"Unexpected error: {e}"

488

489

# Usage with error handling

490

success, result = safe_command_execution(['git', 'status'], cwd='/repo')

491

if success:

492

print(f"Git status: {result}")

493

else:

494

logging.error(f"Git command failed: {result}")

495

```

496

497

The API package provides a clean, pure Python interface to xonsh's powerful subprocess and OS utilities, making it easy to integrate xonsh capabilities into external tools and libraries without requiring a full xonsh shell environment.