or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

constants-reference.mdconstraint-solving.mddevice-management.mddisk-operations.mdexception-handling.mdfilesystem-operations.mdgeometry-alignment.mdindex.mdpartition-management.mdutility-functions.md

exception-handling.mddocs/

0

# Exception Handling

1

2

pyparted provides comprehensive exception handling with specific exception types for different error conditions. The exception system includes both high-level Python exceptions and low-level libparted exception handling.

3

4

## Capabilities

5

6

### Exception Classes

7

8

Specific exception types for different categories of errors.

9

10

```python { .api }

11

# Core operation exceptions

12

class AlignmentException(Exception):

13

"""Raised when alignment operations fail."""

14

15

class ConstraintException(Exception):

16

"""Raised when constraint operations fail or constraints cannot be satisfied."""

17

18

class CreateException(Exception):

19

"""Raised when object creation fails."""

20

21

class DeviceException(Exception):

22

"""Raised when device operations fail."""

23

24

class DiskException(Exception):

25

"""Raised when disk operations fail."""

26

27

class DiskLabelException(Exception):

28

"""Raised when disk label operations fail."""

29

30

class FileSystemException(Exception):

31

"""Raised when filesystem operations fail."""

32

33

class GeometryException(Exception):

34

"""Raised when geometry operations fail."""

35

36

class IOException(Exception):

37

"""Raised when I/O operations fail."""

38

39

class PartitionException(Exception):

40

"""Raised when partition operations fail."""

41

42

class TimerException(Exception):

43

"""Raised when timer operations fail."""

44

45

# Discovery exceptions

46

class UnknownDeviceException(Exception):

47

"""Raised when device cannot be identified."""

48

49

class UnknownTypeException(Exception):

50

"""Raised when type cannot be identified or is invalid."""

51

52

# General exceptions

53

class PartedException(Exception):

54

"""General pyparted exception base class."""

55

56

class NotNeededException(Exception):

57

"""Raised when operation is not needed."""

58

59

# Property access exceptions

60

class ReadOnlyProperty(Exception):

61

"""Raised when attempting to write to read-only property."""

62

63

class WriteOnlyProperty(Exception):

64

"""Raised when attempting to read from write-only property."""

65

```

66

67

### Exception Handler Functions

68

69

Functions for managing low-level libparted exception handling.

70

71

```python { .api }

72

def register_exn_handler(handler_function) -> None:

73

"""

74

Register custom exception handler for libparted exceptions.

75

76

Args:

77

handler_function: Function that takes (exception_type, message, options)

78

and returns resolution constant

79

"""

80

81

def clear_exn_handler() -> None:

82

"""

83

Clear registered exception handler, reverting to default handling.

84

"""

85

```

86

87

## Usage Examples

88

89

### Basic Exception Handling

90

91

```python

92

import parted

93

94

def safe_device_access(device_path):

95

"""Safely access device with proper exception handling."""

96

try:

97

device = parted.getDevice(device_path)

98

print(f"Device: {device.model}")

99

return device

100

101

except parted.DeviceException as e:

102

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

103

return None

104

except parted.UnknownDeviceException as e:

105

print(f"Unknown device: {e}")

106

return None

107

except Exception as e:

108

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

109

return None

110

111

# Test with valid and invalid paths

112

devices_to_test = ['/dev/sda', '/dev/nonexistent', '/invalid/path']

113

for device_path in devices_to_test:

114

result = safe_device_access(device_path)

115

print(f"{device_path}: {'Success' if result else 'Failed'}\n")

116

```

117

118

### Comprehensive Disk Operations with Exception Handling

119

120

```python

121

import parted

122

123

def safe_disk_operations(device_path):

124

"""Perform disk operations with comprehensive error handling."""

125

try:

126

# Get device

127

device = parted.getDevice(device_path)

128

print(f"Found device: {device.model}")

129

130

# Read disk

131

try:

132

disk = parted.newDisk(device)

133

print(f"Disk type: {disk.type}")

134

135

# List partitions

136

for partition in disk.partitions:

137

try:

138

size = partition.getSize('GB')

139

print(f"Partition {partition.number}: {size:.1f} GB")

140

141

# Check flags safely

142

if partition.isFlagAvailable(parted.PARTITION_BOOT):

143

boot_flag = partition.getFlag(parted.PARTITION_BOOT)

144

print(f" Boot flag: {boot_flag}")

145

146

except parted.PartitionException as e:

147

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

148

149

except parted.DiskException as e:

150

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

151

except parted.DiskLabelException as e:

152

print(f"Disk label error: {e}")

153

154

except parted.DeviceException as e:

155

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

156

except parted.IOException as e:

157

print(f"I/O error: {e}")

158

except Exception as e:

159

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

160

161

safe_disk_operations('/dev/sda')

162

```

163

164

### Partition Creation with Error Recovery

165

166

```python

167

import parted

168

169

def create_partition_with_recovery(device_path, size_gb):

170

"""Create partition with error recovery and fallback strategies."""

171

try:

172

device = parted.getDevice(device_path)

173

disk = parted.newDisk(device)

174

175

# Calculate partition geometry

176

size_sectors = int(size_gb * (1024**3) / device.sectorSize)

177

start_sector = 2048

178

179

try:

180

# Try optimal alignment first

181

constraint = device.getOptimalAlignedConstraint()

182

183

try:

184

geometry = parted.Geometry(device, start=start_sector, length=size_sectors)

185

186

# Check if geometry satisfies constraint

187

if constraint.isSolution(geometry):

188

print("Using requested geometry")

189

final_geometry = geometry

190

else:

191

print("Adjusting geometry to satisfy constraints")

192

final_geometry = constraint.solveNearest(geometry)

193

194

# Create partition

195

partition = parted.Partition(

196

disk=disk,

197

type=parted.PARTITION_NORMAL,

198

geometry=final_geometry

199

)

200

201

disk.addPartition(partition, constraint)

202

disk.commit()

203

204

print(f"Successfully created partition: {partition.path}")

205

return True

206

207

except parted.GeometryException as e:

208

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

209

# Try with minimal constraint

210

print("Retrying with minimal alignment...")

211

constraint = device.getMinimalAlignedConstraint()

212

# ... retry logic here

213

214

except parted.ConstraintException as e:

215

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

216

# Try with device-wide constraint

217

print("Retrying with device constraint...")

218

constraint = device.getConstraint()

219

# ... retry logic here

220

221

except parted.CreateException as e:

222

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

223

return False

224

except parted.PartitionException as e:

225

print(f"Partition operation failed: {e}")

226

return False

227

except parted.DiskException as e:

228

print(f"Disk operation failed: {e}")

229

return False

230

except Exception as e:

231

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

232

return False

233

234

create_partition_with_recovery('/dev/sdb', 10) # 10GB partition

235

```

236

237

### Custom Exception Handler

238

239

```python

240

import parted

241

import sys

242

243

def interactive_exception_handler(exception_type, message, options):

244

"""Interactive exception handler for user decisions."""

245

246

# Map exception types to readable names

247

type_names = {

248

parted.EXCEPTION_TYPE_INFORMATION: "INFO",

249

parted.EXCEPTION_TYPE_WARNING: "WARNING",

250

parted.EXCEPTION_TYPE_ERROR: "ERROR",

251

parted.EXCEPTION_TYPE_FATAL: "FATAL",

252

parted.EXCEPTION_TYPE_BUG: "BUG",

253

parted.EXCEPTION_TYPE_NO_FEATURE: "NO_FEATURE"

254

}

255

256

type_name = type_names.get(exception_type, f"UNKNOWN({exception_type})")

257

print(f"\n{type_name}: {message}")

258

259

# Handle based on available options

260

if options == parted.EXCEPTION_OPT_OK_CANCEL:

261

response = input("Continue? (o)k/(c)ancel: ").lower()

262

return parted.EXCEPTION_RESOLVE_OK if response == 'o' else parted.EXCEPTION_RESOLVE_CANCEL

263

264

elif options == parted.EXCEPTION_OPT_YES_NO:

265

response = input("Continue? (y)es/(n)o: ").lower()

266

return parted.EXCEPTION_RESOLVE_YES if response == 'y' else parted.EXCEPTION_RESOLVE_NO

267

268

elif options == parted.EXCEPTION_OPT_YES_NO_CANCEL:

269

response = input("Action? (y)es/(n)o/(c)ancel: ").lower()

270

if response == 'y':

271

return parted.EXCEPTION_RESOLVE_YES

272

elif response == 'n':

273

return parted.EXCEPTION_RESOLVE_NO

274

else:

275

return parted.EXCEPTION_RESOLVE_CANCEL

276

277

elif options == parted.EXCEPTION_OPT_RETRY_CANCEL:

278

response = input("Action? (r)etry/(c)ancel: ").lower()

279

return parted.EXCEPTION_RESOLVE_RETRY if response == 'r' else parted.EXCEPTION_RESOLVE_CANCEL

280

281

elif options == parted.EXCEPTION_OPT_RETRY_IGNORE_CANCEL:

282

response = input("Action? (r)etry/(i)gnore/(c)ancel: ").lower()

283

if response == 'r':

284

return parted.EXCEPTION_RESOLVE_RETRY

285

elif response == 'i':

286

return parted.EXCEPTION_RESOLVE_IGNORE

287

else:

288

return parted.EXCEPTION_RESOLVE_CANCEL

289

290

elif options == parted.EXCEPTION_OPT_IGNORE_CANCEL:

291

response = input("Action? (i)gnore/(c)ancel: ").lower()

292

return parted.EXCEPTION_RESOLVE_IGNORE if response == 'i' else parted.EXCEPTION_RESOLVE_CANCEL

293

294

# Default to unhandled

295

return parted.EXCEPTION_RESOLVE_UNHANDLED

296

297

# Register the handler

298

parted.register_exn_handler(interactive_exception_handler)

299

300

# Use in operations

301

try:

302

device = parted.getDevice('/dev/sdb')

303

# ... perform operations that might trigger exceptions

304

print("Operations completed")

305

finally:

306

# Clean up handler

307

parted.clear_exn_handler()

308

```

309

310

### Logging Exception Handler

311

312

```python

313

import parted

314

import logging

315

import datetime

316

317

# Set up logging

318

logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

319

logger = logging.getLogger('pyparted')

320

321

def logging_exception_handler(exception_type, message, options):

322

"""Exception handler that logs all exceptions."""

323

324

type_names = {

325

parted.EXCEPTION_TYPE_INFORMATION: "INFO",

326

parted.EXCEPTION_TYPE_WARNING: "WARNING",

327

parted.EXCEPTION_TYPE_ERROR: "ERROR",

328

parted.EXCEPTION_TYPE_FATAL: "FATAL",

329

parted.EXCEPTION_TYPE_BUG: "BUG",

330

parted.EXCEPTION_TYPE_NO_FEATURE: "NO_FEATURE"

331

}

332

333

type_name = type_names.get(exception_type, f"UNKNOWN({exception_type})")

334

335

# Log the exception

336

if exception_type == parted.EXCEPTION_TYPE_INFORMATION:

337

logger.info(f"libparted: {message}")

338

return parted.EXCEPTION_RESOLVE_OK

339

elif exception_type == parted.EXCEPTION_TYPE_WARNING:

340

logger.warning(f"libparted: {message}")

341

return parted.EXCEPTION_RESOLVE_OK

342

elif exception_type == parted.EXCEPTION_TYPE_ERROR:

343

logger.error(f"libparted: {message}")

344

# For non-interactive use, generally continue with "fix" or "ok"

345

return parted.EXCEPTION_RESOLVE_FIX

346

elif exception_type == parted.EXCEPTION_TYPE_FATAL:

347

logger.critical(f"libparted: {message}")

348

return parted.EXCEPTION_RESOLVE_CANCEL

349

else:

350

logger.error(f"libparted {type_name}: {message}")

351

return parted.EXCEPTION_RESOLVE_UNHANDLED

352

353

# Register logging handler

354

parted.register_exn_handler(logging_exception_handler)

355

356

def logged_disk_operations(device_path):

357

"""Perform disk operations with comprehensive logging."""

358

logger.info(f"Starting disk operations on {device_path}")

359

360

try:

361

device = parted.getDevice(device_path)

362

logger.info(f"Device opened: {device.model}")

363

364

disk = parted.newDisk(device)

365

logger.info(f"Disk read: {disk.type} with {len(disk.partitions)} partitions")

366

367

# Operations that might trigger libparted exceptions

368

if not disk.check():

369

logger.warning("Disk consistency check failed")

370

371

return True

372

373

except Exception as e:

374

logger.error(f"Operation failed: {e}")

375

return False

376

finally:

377

logger.info("Disk operations completed")

378

379

logged_disk_operations('/dev/sda')

380

```

381

382

### Exception Context Manager

383

384

```python

385

import parted

386

from contextlib import contextmanager

387

388

@contextmanager

389

def exception_handler_context(handler_func):

390

"""Context manager for temporary exception handler."""

391

parted.register_exn_handler(handler_func)

392

try:

393

yield

394

finally:

395

parted.clear_exn_handler()

396

397

def silent_handler(exception_type, message, options):

398

"""Silent handler that automatically resolves exceptions."""

399

if exception_type in [parted.EXCEPTION_TYPE_INFORMATION, parted.EXCEPTION_TYPE_WARNING]:

400

return parted.EXCEPTION_RESOLVE_OK

401

elif exception_type == parted.EXCEPTION_TYPE_ERROR:

402

return parted.EXCEPTION_RESOLVE_FIX

403

else:

404

return parted.EXCEPTION_RESOLVE_CANCEL

405

406

# Use context manager for specific operations

407

with exception_handler_context(silent_handler):

408

try:

409

device = parted.getDevice('/dev/sda')

410

disk = parted.newDisk(device)

411

# Perform operations with silent exception handling

412

print(f"Processed disk with {len(disk.partitions)} partitions")

413

except Exception as e:

414

print(f"Error: {e}")

415

416

print("Back to default exception handling")

417

```

418

419

### Exception Analysis and Reporting

420

421

```python

422

import parted

423

from collections import defaultdict

424

425

class ExceptionTracker:

426

"""Track and analyze exceptions during operations."""

427

428

def __init__(self):

429

self.exceptions = []

430

self.counts = defaultdict(int)

431

432

def handler(self, exception_type, message, options):

433

"""Exception handler that tracks exceptions."""

434

self.exceptions.append({

435

'type': exception_type,

436

'message': message,

437

'options': options,

438

'timestamp': parted.time.time()

439

})

440

self.counts[exception_type] += 1

441

442

# Provide reasonable default responses

443

if exception_type in [parted.EXCEPTION_TYPE_INFORMATION, parted.EXCEPTION_TYPE_WARNING]:

444

return parted.EXCEPTION_RESOLVE_OK

445

elif exception_type == parted.EXCEPTION_TYPE_ERROR:

446

return parted.EXCEPTION_RESOLVE_FIX

447

else:

448

return parted.EXCEPTION_RESOLVE_CANCEL

449

450

def report(self):

451

"""Generate exception report."""

452

if not self.exceptions:

453

print("No exceptions occurred")

454

return

455

456

type_names = {

457

parted.EXCEPTION_TYPE_INFORMATION: "INFO",

458

parted.EXCEPTION_TYPE_WARNING: "WARNING",

459

parted.EXCEPTION_TYPE_ERROR: "ERROR",

460

parted.EXCEPTION_TYPE_FATAL: "FATAL",

461

parted.EXCEPTION_TYPE_BUG: "BUG",

462

parted.EXCEPTION_TYPE_NO_FEATURE: "NO_FEATURE"

463

}

464

465

print(f"\nException Report: {len(self.exceptions)} total exceptions")

466

print("Summary by type:")

467

for exc_type, count in self.counts.items():

468

type_name = type_names.get(exc_type, f"UNKNOWN({exc_type})")

469

print(f" {type_name}: {count}")

470

471

print("\nDetailed exceptions:")

472

for i, exc in enumerate(self.exceptions, 1):

473

type_name = type_names.get(exc['type'], f"UNKNOWN({exc['type']})")

474

print(f" {i}. {type_name}: {exc['message']}")

475

476

# Use exception tracker

477

tracker = ExceptionTracker()

478

479

with exception_handler_context(tracker.handler):

480

try:

481

# Perform operations that might generate exceptions

482

devices = parted.getAllDevices()

483

for device in devices:

484

try:

485

disk = parted.newDisk(device)

486

disk.check()

487

except:

488

continue # Continue processing other devices

489

except Exception as e:

490

print(f"Error: {e}")

491

492

tracker.report()

493

```

494

495

## Exception Hierarchy

496

497

### Base Exceptions

498

- `PartedException` - Base class for all pyparted exceptions

499

- `Exception` - Python base exception class

500

501

### Specific Exception Categories

502

503

**Object Creation**:

504

- `CreateException` - Object creation failures

505

- `AlignmentException` - Alignment creation/operation failures

506

- `ConstraintException` - Constraint creation/solving failures

507

508

**Device/Disk Operations**:

509

- `DeviceException` - Device access/operation failures

510

- `DiskException` - Disk/partition table failures

511

- `DiskLabelException` - Disk label specific failures

512

- `IOException` - Low-level I/O failures

513

514

**Partition Operations**:

515

- `PartitionException` - Partition-specific failures

516

- `GeometryException` - Geometry calculation/validation failures

517

- `FileSystemException` - Filesystem operation failures

518

519

**Discovery/Identification**:

520

- `UnknownDeviceException` - Device identification failures

521

- `UnknownTypeException` - Type identification failures

522

523

## Best Practices

524

525

1. **Specific Exception Handling**: Catch specific exceptions rather than generic Exception

526

2. **Progressive Fallback**: Try optimal approaches first, fall back to simpler ones

527

3. **Resource Cleanup**: Use try/finally or context managers for cleanup

528

4. **User Feedback**: Provide meaningful error messages to users

529

5. **Logging**: Log exceptions for debugging and monitoring

530

6. **Exception Handlers**: Use custom handlers for automated or interactive scenarios