or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

bases.mdexceptions.mdindex.mdinference.mdmanager.mdnodes.mdparsing.md

exceptions.mddocs/

0

# Exception Handling

1

2

Comprehensive exception hierarchy for handling various error conditions during AST building, inference, and analysis operations. Understanding these exceptions is crucial for robust astroid-based tools.

3

4

## Capabilities

5

6

### Core Exception Classes

7

8

Base exceptions that form the foundation of astroid's error handling system.

9

10

```python { .api }

11

class AstroidError(Exception):

12

"""Base class for all astroid exceptions."""

13

14

class AstroidBuildingError(AstroidError):

15

"""

16

Raised when AST building fails.

17

18

This includes failures to:

19

- Read source files

20

- Parse Python syntax

21

- Import modules

22

- Introspect live objects

23

"""

24

25

class AstroidSyntaxError(AstroidError):

26

"""

27

Raised when Python source code contains syntax errors.

28

29

Attributes:

30

- lineno: Line number of syntax error

31

- offset: Character offset of error

32

- text: Source line containing error

33

- filename: File containing the error

34

"""

35

36

class AstroidImportError(AstroidError):

37

"""

38

Raised when module imports fail.

39

40

This includes:

41

- Module not found

42

- Import permission errors

43

- Circular import detection

44

"""

45

```

46

47

### Type-Related Exceptions

48

49

Exceptions for type checking and validation errors.

50

51

```python { .api }

52

class AstroidTypeError(AstroidError):

53

"""

54

Raised when type-related operations fail.

55

56

Examples:

57

- Invalid type annotations

58

- Unsupported type operations

59

- Type constraint violations

60

"""

61

62

class AstroidValueError(AstroidError):

63

"""

64

Raised when value-related operations fail.

65

66

Examples:

67

- Invalid constant values

68

- Value conversion errors

69

- Range/boundary violations

70

"""

71

72

class AstroidIndexError(AstroidError):

73

"""

74

Raised when indexing operations fail.

75

76

Examples:

77

- List/tuple index out of range

78

- Invalid sequence access

79

- Dictionary key errors

80

"""

81

```

82

83

### Inference Exception Hierarchy

84

85

Specialized exceptions for the inference system.

86

87

```python { .api }

88

class InferenceError(AstroidError):

89

"""

90

Base class for all inference failures.

91

92

Inference can fail for many reasons:

93

- Unresolvable names

94

- Complex control flow

95

- Dynamic attribute access

96

- Runtime-dependent values

97

"""

98

99

class NameInferenceError(InferenceError):

100

"""

101

Raised when name lookup fails during inference.

102

103

Common causes:

104

- Undefined variables

105

- Names not in scope

106

- Import resolution failures

107

"""

108

109

class AttributeInferenceError(InferenceError):

110

"""

111

Raised when attribute access cannot be inferred.

112

113

Common causes:

114

- Dynamic attribute creation

115

- Descriptor protocol complexity

116

- Missing attribute definitions

117

"""

118

119

class InferenceOverwriteError(InferenceError):

120

"""

121

Raised when trying to overwrite existing inference tips.

122

123

This prevents accidental replacement of inference behavior

124

for built-in or previously registered functions.

125

"""

126

127

class UseInferenceDefault(InferenceError):

128

"""

129

Special exception to request fallback to default inference.

130

131

Used in custom inference tips to delegate back to

132

the standard inference mechanism.

133

"""

134

```

135

136

### MRO and Inheritance Exceptions

137

138

Exceptions related to method resolution order and class inheritance.

139

140

```python { .api }

141

class MroError(AstroidError):

142

"""

143

Base class for Method Resolution Order errors.

144

145

The MRO determines the order in which base classes

146

are searched for methods and attributes.

147

"""

148

149

class DuplicateBasesError(MroError):

150

"""

151

Raised when a class has duplicate base classes.

152

153

Example:

154

class Bad(Base, Base): # Duplicate base

155

pass

156

"""

157

158

class InconsistentMroError(MroError):

159

"""

160

Raised when MRO cannot be computed consistently.

161

162

This occurs with complex multiple inheritance

163

hierarchies that violate Python's MRO rules.

164

"""

165

166

class SuperError(AstroidError):

167

"""

168

Raised when super() calls cannot be resolved.

169

170

Common causes:

171

- Invalid super() usage

172

- Missing method in parent classes

173

- Complex MRO scenarios

174

"""

175

176

class SuperArgumentTypeError(SuperError):

177

"""

178

Raised when super() arguments have wrong types.

179

180

super() expects specific argument types depending

181

on the calling context.

182

"""

183

```

184

185

### Resolution and Lookup Exceptions

186

187

Exceptions for name and symbol resolution failures.

188

189

```python { .api }

190

class ResolveError(AstroidError):

191

"""

192

Raised when symbol resolution fails.

193

194

This covers various resolution failures beyond

195

simple name lookup.

196

"""

197

198

class NotFoundError(AttributeInferenceError):

199

"""

200

Alias for AttributeInferenceError.

201

202

Maintained for backward compatibility.

203

"""

204

205

class UnresolvableName(NameInferenceError):

206

"""

207

Alias for NameInferenceError.

208

209

Raised when a name cannot be resolved in any scope.

210

"""

211

```

212

213

### Structural and Validation Exceptions

214

215

Exceptions for AST structure and validation issues.

216

217

```python { .api }

218

class ParentMissingError(AstroidError):

219

"""

220

Raised when a node is missing its required parent.

221

222

Some operations require nodes to be properly

223

connected in the AST hierarchy.

224

"""

225

226

class StatementMissing(AstroidError):

227

"""

228

Raised when a required statement cannot be found.

229

230

Some analyses require specific statement types

231

to be present in the AST.

232

"""

233

234

class TooManyLevelsError(AstroidError):

235

"""

236

Raised when relative imports go too deep.

237

238

Example:

239

from ....module import something # Too many levels

240

"""

241

```

242

243

### Special Value Exceptions

244

245

Exceptions representing special states rather than errors.

246

247

```python { .api }

248

class NoDefault(AstroidError):

249

"""

250

Raised when no default value is available.

251

252

Used in contexts where a default value is requested

253

but none exists (e.g., function parameters).

254

"""

255

```

256

257

## Usage Examples

258

259

### Basic Exception Handling

260

261

```python

262

import astroid

263

264

# Handle building errors

265

try:

266

module = astroid.parse("invalid syntax here $$")

267

except astroid.AstroidSyntaxError as e:

268

print(f"Syntax error at line {e.lineno}: {e.msg}")

269

270

# Handle import errors

271

try:

272

module = astroid.MANAGER.ast_from_module_name("nonexistent_module")

273

except astroid.AstroidImportError as e:

274

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

275

276

# Handle inference errors

277

code = "x = unknown_variable"

278

module = astroid.parse(code)

279

name_node = next(module.nodes_of_class(astroid.Name))

280

281

try:

282

list(name_node.infer())

283

except astroid.NameInferenceError as e:

284

print(f"Cannot infer name: {e}")

285

```

286

287

### Specific Error Handling

288

289

```python

290

import astroid

291

292

# Handle attribute inference

293

code = '''

294

class MyClass:

295

pass

296

297

obj = MyClass()

298

value = obj.nonexistent_attr

299

'''

300

301

module = astroid.parse(code)

302

attr_node = next(module.nodes_of_class(astroid.Attribute))

303

304

try:

305

list(attr_node.infer())

306

except astroid.AttributeInferenceError as e:

307

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

308

except astroid.InferenceError as e:

309

print(f"General inference error: {e}")

310

```

311

312

### MRO Error Handling

313

314

```python

315

import astroid

316

317

# This would cause MRO issues in complex hierarchies

318

complex_code = '''

319

class A(object): pass

320

class B(A): pass

321

class C(A): pass

322

class D(B, C): pass # This is fine

323

'''

324

325

try:

326

module = astroid.parse(complex_code)

327

d_class = next(node for node in module.body if isinstance(node, astroid.ClassDef) and node.name == 'D')

328

mro = d_class.mro()

329

print(f"MRO: {[cls.name for cls in mro]}")

330

except astroid.MroError as e:

331

print(f"MRO computation failed: {e}")

332

```

333

334

### Safe Operations with Exception Handling

335

336

```python

337

import astroid

338

339

def safe_infer_name(node):

340

"""Safely infer a name node."""

341

try:

342

return list(node.infer())

343

except astroid.NameInferenceError:

344

return []

345

except astroid.InferenceError:

346

return []

347

348

def safe_get_attribute(node, attr_name):

349

"""Safely get an attribute from a node."""

350

try:

351

return node[attr_name]

352

except (KeyError, astroid.NotFoundError):

353

return None

354

355

# Usage

356

code = "x = some_function()"

357

module = astroid.parse(code)

358

359

for name in module.nodes_of_class(astroid.Name):

360

inferred = safe_infer_name(name)

361

print(f"Name {name.name}: {len(inferred)} inferences")

362

```

363

364

### Custom Exception Handling

365

366

```python

367

import astroid

368

369

class CustomAnalysisError(astroid.AstroidError):

370

"""Custom exception for analysis tools."""

371

pass

372

373

def analyze_function(func_node):

374

"""Analyze a function with custom error handling."""

375

if not isinstance(func_node, astroid.FunctionDef):

376

raise CustomAnalysisError("Expected function definition")

377

378

try:

379

# Analyze function body

380

if not func_node.body:

381

raise CustomAnalysisError("Function has no body")

382

383

# Check for return statements

384

returns = list(func_node.nodes_of_class(astroid.Return))

385

if not returns:

386

raise CustomAnalysisError("Function has no return statement")

387

388

except astroid.InferenceError as e:

389

raise CustomAnalysisError(f"Inference failed during analysis: {e}")

390

391

# Usage with proper error handling

392

code = '''

393

def empty_func():

394

pass

395

396

def good_func():

397

return 42

398

'''

399

400

module = astroid.parse(code)

401

for func in module.nodes_of_class(astroid.FunctionDef):

402

try:

403

analyze_function(func)

404

print(f"Function {func.name} analyzed successfully")

405

except CustomAnalysisError as e:

406

print(f"Analysis failed for {func.name}: {e}")

407

```

408

409

## Error Recovery Strategies

410

411

### Graceful Degradation

412

413

```python

414

import astroid

415

416

def robust_analysis(code):

417

"""Perform analysis with graceful error handling."""

418

try:

419

module = astroid.parse(code)

420

except astroid.AstroidSyntaxError:

421

return {"error": "syntax_error", "analysis": None}

422

except astroid.AstroidError as e:

423

return {"error": "parsing_error", "details": str(e)}

424

425

analysis_results = {}

426

427

# Safe function analysis

428

functions = []

429

for func in module.nodes_of_class(astroid.FunctionDef):

430

func_info = {"name": func.name, "args": len(func.args.args)}

431

try:

432

# Try to infer return type

433

returns = list(func.nodes_of_class(astroid.Return))

434

if returns:

435

inferred = astroid.safe_infer(returns[0].value)

436

func_info["return_type"] = type(inferred).__name__ if inferred else "unknown"

437

except Exception:

438

func_info["return_type"] = "error"

439

functions.append(func_info)

440

441

analysis_results["functions"] = functions

442

return {"error": None, "analysis": analysis_results}

443

```

444

445

### Exception Chaining

446

447

```python

448

import astroid

449

450

def detailed_error_reporting(code):

451

"""Provide detailed error information."""

452

try:

453

module = astroid.parse(code)

454

return module

455

except astroid.AstroidSyntaxError as e:

456

# Chain with more context

457

raise astroid.AstroidBuildingError(f"Syntax error in code: {e}") from e

458

except Exception as e:

459

# Wrap unexpected errors

460

raise astroid.AstroidError(f"Unexpected error during parsing: {e}") from e

461

```

462

463

## Best Practices

464

465

1. **Always handle AstroidError**: Use the base class to catch all astroid-related exceptions

466

2. **Use safe_infer() when appropriate**: Avoid exception handling for simple cases

467

3. **Provide fallback behavior**: Have default actions when operations fail

468

4. **Log errors appropriately**: Capture enough context for debugging

469

5. **Chain exceptions**: Preserve original error information when re-raising