or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

completion.mdhistory.mdhooks.mdindex.mdline-editing.mdutilities.md

utilities.mddocs/

0

# Utilities

1

2

Utility modules and scripts that complement the core gnureadline functionality, including system integration and alternative import mechanisms.

3

4

## readline.py Module

5

6

Pure Python wrapper module that imports all gnureadline functionality for systems without a built-in readline module.

7

8

```python { .api }

9

# All gnureadline functions are available through this module

10

from gnureadline import *

11

from gnureadline import __doc__

12

```

13

14

### Usage

15

16

This module is designed for systems like ActiveState Python that have no default readline module at all.

17

18

```python

19

# For systems without any readline module

20

import readline # This will import the gnureadline wrapper

21

22

# All gnureadline functions are now available as readline functions

23

readline.add_history("test command")

24

readline.set_completer(my_completer)

25

```

26

27

**Warning**: This module should not be used to override an existing system readline. Use the `override_readline` module instead for that purpose.

28

29

## override_readline Module

30

31

Installation utility for system-wide readline replacement via Python's site customization mechanism. This script safely overrides the default readline module with gnureadline.

32

33

### Core Functions

34

35

```python { .api }

36

def main() -> int:

37

"""

38

Main entry point for override installation.

39

40

Returns:

41

int: Exit code (0 for success, 1 for failure)

42

"""

43

44

def check_module(module_name: str):

45

"""

46

Import and analyze a readline module.

47

48

Parameters:

49

- module_name: Name of module to check ('readline' or 'gnureadline')

50

51

Returns:

52

module or None: Imported module or None if import failed

53

"""

54

55

def install_override(customize_path: str):

56

"""

57

Install readline override in specified customization file.

58

59

Parameters:

60

- customize_path: Path to sitecustomize.py or usercustomize.py

61

"""

62

63

def override_usercustomize() -> bool:

64

"""

65

Install override in user site customization.

66

67

Returns:

68

bool: True if successful, False if failed

69

"""

70

71

def override_sitecustomize() -> bool:

72

"""

73

Install override in site customization.

74

75

Returns:

76

bool: True if successful, False if failed

77

"""

78

```

79

80

### Command-Line Usage

81

82

The recommended way to use the override module is as a script:

83

84

```bash

85

# Install override for current Python interpreter (tries user site first)

86

python -m override_readline

87

88

# Install in site customization (system-wide, skips user site)

89

python -s -m override_readline

90

91

# For specific Python version

92

python3.11 -m override_readline

93

```

94

95

### Usage Examples

96

97

```python

98

import override_readline

99

100

# Check what readline modules are available

101

print("Checking available readline modules:")

102

readline_mod = override_readline.check_module("readline")

103

gnureadline_mod = override_readline.check_module("gnureadline")

104

105

if gnureadline_mod:

106

print("gnureadline is available")

107

if readline_mod == gnureadline_mod:

108

print("readline is already overridden with gnureadline")

109

else:

110

print("readline is using a different implementation")

111

112

# Install override programmatically

113

try:

114

success = override_readline.override_usercustomize()

115

if success:

116

print("Override installed in user customization")

117

else:

118

success = override_readline.override_sitecustomize()

119

if success:

120

print("Override installed in site customization")

121

else:

122

print("Failed to install override")

123

except Exception as e:

124

print(f"Error installing override: {e}")

125

```

126

127

## Advanced Integration Examples

128

129

### Custom Site Customization

130

131

For advanced users who want to customize the override behavior:

132

133

```python

134

# Example custom sitecustomize.py content

135

import sys

136

137

def setup_gnureadline():

138

"""Custom gnureadline setup with additional configuration."""

139

try:

140

import gnureadline as readline

141

142

# Custom configuration

143

readline.set_history_length(2000)

144

readline.parse_and_bind("set bell-style none")

145

readline.parse_and_bind("set completion-ignore-case on")

146

147

# Load history file

148

import os

149

import atexit

150

151

history_file = os.path.expanduser("~/.python_history")

152

try:

153

readline.read_history_file(history_file)

154

except FileNotFoundError:

155

pass

156

157

# Save history on exit

158

def save_history():

159

try:

160

readline.write_history_file(history_file)

161

except OSError:

162

pass

163

164

atexit.register(save_history)

165

166

# Add interactive hook message

167

def add_override_message():

168

try:

169

old_hook = sys.__interactivehook__

170

except AttributeError:

171

return

172

173

def hook():

174

old_hook()

175

print("Using GNU readline with custom configuration")

176

177

sys.__interactivehook__ = hook

178

179

add_override_message()

180

181

except ImportError:

182

import readline

183

184

# Make readline available globally

185

sys.modules["readline"] = readline

186

187

# Set up readline override

188

setup_gnureadline()

189

```

190

191

### Environment-Specific Configuration

192

193

```python

194

# Environment-aware override setup

195

import os

196

import sys

197

198

def setup_readline_for_environment():

199

"""Set up readline based on environment."""

200

try:

201

import gnureadline as readline

202

203

# Different configs for different environments

204

if os.environ.get('DEVELOPMENT_MODE'):

205

# Development environment - more verbose

206

readline.parse_and_bind("set bell-style audible")

207

readline.set_history_length(5000)

208

209

# Enable all completions

210

readline.parse_and_bind("set completion-ignore-case on")

211

readline.parse_and_bind("set show-all-if-ambiguous on")

212

213

elif os.environ.get('PRODUCTION_MODE'):

214

# Production environment - minimal

215

readline.parse_and_bind("set bell-style none")

216

readline.set_history_length(100)

217

218

else:

219

# Default environment

220

readline.set_history_length(1000)

221

readline.parse_and_bind("set bell-style none")

222

223

# Environment-specific history files

224

env_name = os.environ.get('ENVIRONMENT', 'default')

225

history_file = os.path.expanduser(f"~/.python_history_{env_name}")

226

227

try:

228

readline.read_history_file(history_file)

229

except FileNotFoundError:

230

pass

231

232

import atexit

233

atexit.register(lambda: readline.write_history_file(history_file))

234

235

except ImportError:

236

import readline

237

238

sys.modules["readline"] = readline

239

240

setup_readline_for_environment()

241

```

242

243

### Application-Specific Override

244

245

```python

246

# Application-specific readline configuration

247

import sys

248

import os

249

250

class ApplicationReadline:

251

"""Application-specific readline wrapper."""

252

253

def __init__(self, app_name):

254

self.app_name = app_name

255

self.setup_readline()

256

257

def setup_readline(self):

258

"""Set up readline for this application."""

259

try:

260

import gnureadline as readline

261

self.readline = readline

262

263

# App-specific configuration

264

config_file = os.path.expanduser(f"~/.{self.app_name}_inputrc")

265

if os.path.exists(config_file):

266

readline.read_init_file(config_file)

267

268

# App-specific history

269

self.history_file = os.path.expanduser(f"~/.{self.app_name}_history")

270

try:

271

readline.read_history_file(self.history_file)

272

except FileNotFoundError:

273

pass

274

275

# Set up save on exit

276

import atexit

277

atexit.register(self.save_history)

278

279

# Custom completer

280

readline.set_completer(self.app_completer)

281

readline.parse_and_bind("tab: complete")

282

283

except ImportError:

284

import readline

285

self.readline = readline

286

287

def app_completer(self, text, state):

288

"""Application-specific completer."""

289

# Implement app-specific completion logic

290

app_commands = ['start', 'stop', 'status', 'config', 'help', 'quit']

291

matches = [cmd for cmd in app_commands if cmd.startswith(text)]

292

293

try:

294

return matches[state]

295

except IndexError:

296

return None

297

298

def save_history(self):

299

"""Save application history."""

300

try:

301

self.readline.write_history_file(self.history_file)

302

except (OSError, AttributeError):

303

pass

304

305

def get_readline(self):

306

"""Get the configured readline module."""

307

return self.readline

308

309

# Usage in application

310

def setup_app_readline(app_name):

311

"""Set up application-specific readline."""

312

app_readline = ApplicationReadline(app_name)

313

readline = app_readline.get_readline()

314

315

# Make it available as the readline module

316

sys.modules["readline"] = readline

317

318

return readline

319

320

# Example usage

321

# readline = setup_app_readline("myapp")

322

```

323

324

## Troubleshooting Utilities

325

326

### Diagnostic Functions

327

328

```python

329

import sys

330

331

def diagnose_readline():

332

"""Diagnose readline configuration and issues."""

333

print("=== Readline Diagnosis ===")

334

335

# Check if readline is available

336

try:

337

import readline

338

print(f"✓ readline module imported: {readline.__file__}")

339

print(f" Documentation: {readline.__doc__[:100]}...")

340

341

# Check if it's GNU readline or libedit

342

if hasattr(readline, 'backend'):

343

print(f" Backend: {readline.backend}")

344

elif "GNU" in readline.__doc__:

345

print(" Backend: GNU readline")

346

elif "libedit" in readline.__doc__:

347

print(" Backend: libedit")

348

else:

349

print(" Backend: unknown")

350

351

except ImportError:

352

print("✗ readline module not available")

353

return

354

355

# Check gnureadline availability

356

try:

357

import gnureadline

358

print(f"✓ gnureadline available: {gnureadline.__file__}")

359

except ImportError:

360

print("✗ gnureadline not available")

361

362

# Check if readline is overridden

363

try:

364

import readline

365

import gnureadline

366

if readline is gnureadline:

367

print("✓ readline is overridden with gnureadline")

368

else:

369

print("⚠ readline is not overridden")

370

except ImportError:

371

pass

372

373

# Check site customization

374

try:

375

import sitecustomize

376

print(f"✓ sitecustomize found: {sitecustomize.__file__}")

377

except ImportError:

378

print("- sitecustomize not found")

379

380

try:

381

import usercustomize

382

print(f"✓ usercustomize found: {usercustomize.__file__}")

383

except ImportError:

384

print("- usercustomize not found")

385

386

# Check history functionality

387

try:

388

readline.add_history("test")

389

if readline.get_current_history_length() > 0:

390

print("✓ History functionality working")

391

else:

392

print("⚠ History functionality not working")

393

except Exception as e:

394

print(f"✗ History error: {e}")

395

396

# Check completion functionality

397

try:

398

readline.set_completer(lambda text, state: None)

399

print("✓ Completion functionality working")

400

except Exception as e:

401

print(f"✗ Completion error: {e}")

402

403

print("=== End Diagnosis ===")

404

405

# diagnose_readline() # Uncomment to run diagnosis

406

```

407

408

## Installation Verification

409

410

```python

411

def verify_gnureadline_installation():

412

"""Verify that gnureadline is properly installed and configured."""

413

issues = []

414

415

# Check basic import

416

try:

417

import gnureadline

418

except ImportError:

419

issues.append("gnureadline cannot be imported - package not installed")

420

return issues

421

422

# Check C extension

423

try:

424

gnureadline.add_history("test")

425

gnureadline.clear_history()

426

except Exception as e:

427

issues.append(f"gnureadline C extension not working: {e}")

428

429

# Check override modules

430

try:

431

import readline as readline_module

432

import override_readline

433

except ImportError as e:

434

issues.append(f"Override modules not available: {e}")

435

436

# Check if override is recommended

437

try:

438

import readline

439

if "libedit" in readline.__doc__:

440

issues.append("System readline is libedit - consider running 'python -m override_readline'")

441

except ImportError:

442

pass

443

444

if not issues:

445

print("✓ gnureadline installation is working correctly")

446

else:

447

print("Issues found:")

448

for issue in issues:

449

print(f" ⚠ {issue}")

450

451

return issues

452

453

# verify_gnureadline_installation() # Uncomment to run verification

454

```