An abstract syntax tree for Python with inference support.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
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.
Base exceptions that form the foundation of astroid's error handling system.
class AstroidError(Exception):
"""Base class for all astroid exceptions."""
class AstroidBuildingError(AstroidError):
"""
Raised when AST building fails.
This includes failures to:
- Read source files
- Parse Python syntax
- Import modules
- Introspect live objects
"""
class AstroidSyntaxError(AstroidError):
"""
Raised when Python source code contains syntax errors.
Attributes:
- lineno: Line number of syntax error
- offset: Character offset of error
- text: Source line containing error
- filename: File containing the error
"""
class AstroidImportError(AstroidError):
"""
Raised when module imports fail.
This includes:
- Module not found
- Import permission errors
- Circular import detection
"""Exceptions for type checking and validation errors.
class AstroidTypeError(AstroidError):
"""
Raised when type-related operations fail.
Examples:
- Invalid type annotations
- Unsupported type operations
- Type constraint violations
"""
class AstroidValueError(AstroidError):
"""
Raised when value-related operations fail.
Examples:
- Invalid constant values
- Value conversion errors
- Range/boundary violations
"""
class AstroidIndexError(AstroidError):
"""
Raised when indexing operations fail.
Examples:
- List/tuple index out of range
- Invalid sequence access
- Dictionary key errors
"""Specialized exceptions for the inference system.
class InferenceError(AstroidError):
"""
Base class for all inference failures.
Inference can fail for many reasons:
- Unresolvable names
- Complex control flow
- Dynamic attribute access
- Runtime-dependent values
"""
class NameInferenceError(InferenceError):
"""
Raised when name lookup fails during inference.
Common causes:
- Undefined variables
- Names not in scope
- Import resolution failures
"""
class AttributeInferenceError(InferenceError):
"""
Raised when attribute access cannot be inferred.
Common causes:
- Dynamic attribute creation
- Descriptor protocol complexity
- Missing attribute definitions
"""
class InferenceOverwriteError(InferenceError):
"""
Raised when trying to overwrite existing inference tips.
This prevents accidental replacement of inference behavior
for built-in or previously registered functions.
"""
class UseInferenceDefault(InferenceError):
"""
Special exception to request fallback to default inference.
Used in custom inference tips to delegate back to
the standard inference mechanism.
"""Exceptions related to method resolution order and class inheritance.
class MroError(AstroidError):
"""
Base class for Method Resolution Order errors.
The MRO determines the order in which base classes
are searched for methods and attributes.
"""
class DuplicateBasesError(MroError):
"""
Raised when a class has duplicate base classes.
Example:
class Bad(Base, Base): # Duplicate base
pass
"""
class InconsistentMroError(MroError):
"""
Raised when MRO cannot be computed consistently.
This occurs with complex multiple inheritance
hierarchies that violate Python's MRO rules.
"""
class SuperError(AstroidError):
"""
Raised when super() calls cannot be resolved.
Common causes:
- Invalid super() usage
- Missing method in parent classes
- Complex MRO scenarios
"""
class SuperArgumentTypeError(SuperError):
"""
Raised when super() arguments have wrong types.
super() expects specific argument types depending
on the calling context.
"""Exceptions for name and symbol resolution failures.
class ResolveError(AstroidError):
"""
Raised when symbol resolution fails.
This covers various resolution failures beyond
simple name lookup.
"""
class NotFoundError(AttributeInferenceError):
"""
Alias for AttributeInferenceError.
Maintained for backward compatibility.
"""
class UnresolvableName(NameInferenceError):
"""
Alias for NameInferenceError.
Raised when a name cannot be resolved in any scope.
"""Exceptions for AST structure and validation issues.
class ParentMissingError(AstroidError):
"""
Raised when a node is missing its required parent.
Some operations require nodes to be properly
connected in the AST hierarchy.
"""
class StatementMissing(AstroidError):
"""
Raised when a required statement cannot be found.
Some analyses require specific statement types
to be present in the AST.
"""
class TooManyLevelsError(AstroidError):
"""
Raised when relative imports go too deep.
Example:
from ....module import something # Too many levels
"""Exceptions representing special states rather than errors.
class NoDefault(AstroidError):
"""
Raised when no default value is available.
Used in contexts where a default value is requested
but none exists (e.g., function parameters).
"""import astroid
# Handle building errors
try:
module = astroid.parse("invalid syntax here $$")
except astroid.AstroidSyntaxError as e:
print(f"Syntax error at line {e.lineno}: {e.msg}")
# Handle import errors
try:
module = astroid.MANAGER.ast_from_module_name("nonexistent_module")
except astroid.AstroidImportError as e:
print(f"Import failed: {e}")
# Handle inference errors
code = "x = unknown_variable"
module = astroid.parse(code)
name_node = next(module.nodes_of_class(astroid.Name))
try:
list(name_node.infer())
except astroid.NameInferenceError as e:
print(f"Cannot infer name: {e}")import astroid
# Handle attribute inference
code = '''
class MyClass:
pass
obj = MyClass()
value = obj.nonexistent_attr
'''
module = astroid.parse(code)
attr_node = next(module.nodes_of_class(astroid.Attribute))
try:
list(attr_node.infer())
except astroid.AttributeInferenceError as e:
print(f"Attribute not found: {e}")
except astroid.InferenceError as e:
print(f"General inference error: {e}")import astroid
# This would cause MRO issues in complex hierarchies
complex_code = '''
class A(object): pass
class B(A): pass
class C(A): pass
class D(B, C): pass # This is fine
'''
try:
module = astroid.parse(complex_code)
d_class = next(node for node in module.body if isinstance(node, astroid.ClassDef) and node.name == 'D')
mro = d_class.mro()
print(f"MRO: {[cls.name for cls in mro]}")
except astroid.MroError as e:
print(f"MRO computation failed: {e}")import astroid
def safe_infer_name(node):
"""Safely infer a name node."""
try:
return list(node.infer())
except astroid.NameInferenceError:
return []
except astroid.InferenceError:
return []
def safe_get_attribute(node, attr_name):
"""Safely get an attribute from a node."""
try:
return node[attr_name]
except (KeyError, astroid.NotFoundError):
return None
# Usage
code = "x = some_function()"
module = astroid.parse(code)
for name in module.nodes_of_class(astroid.Name):
inferred = safe_infer_name(name)
print(f"Name {name.name}: {len(inferred)} inferences")import astroid
class CustomAnalysisError(astroid.AstroidError):
"""Custom exception for analysis tools."""
pass
def analyze_function(func_node):
"""Analyze a function with custom error handling."""
if not isinstance(func_node, astroid.FunctionDef):
raise CustomAnalysisError("Expected function definition")
try:
# Analyze function body
if not func_node.body:
raise CustomAnalysisError("Function has no body")
# Check for return statements
returns = list(func_node.nodes_of_class(astroid.Return))
if not returns:
raise CustomAnalysisError("Function has no return statement")
except astroid.InferenceError as e:
raise CustomAnalysisError(f"Inference failed during analysis: {e}")
# Usage with proper error handling
code = '''
def empty_func():
pass
def good_func():
return 42
'''
module = astroid.parse(code)
for func in module.nodes_of_class(astroid.FunctionDef):
try:
analyze_function(func)
print(f"Function {func.name} analyzed successfully")
except CustomAnalysisError as e:
print(f"Analysis failed for {func.name}: {e}")import astroid
def robust_analysis(code):
"""Perform analysis with graceful error handling."""
try:
module = astroid.parse(code)
except astroid.AstroidSyntaxError:
return {"error": "syntax_error", "analysis": None}
except astroid.AstroidError as e:
return {"error": "parsing_error", "details": str(e)}
analysis_results = {}
# Safe function analysis
functions = []
for func in module.nodes_of_class(astroid.FunctionDef):
func_info = {"name": func.name, "args": len(func.args.args)}
try:
# Try to infer return type
returns = list(func.nodes_of_class(astroid.Return))
if returns:
inferred = astroid.safe_infer(returns[0].value)
func_info["return_type"] = type(inferred).__name__ if inferred else "unknown"
except Exception:
func_info["return_type"] = "error"
functions.append(func_info)
analysis_results["functions"] = functions
return {"error": None, "analysis": analysis_results}import astroid
def detailed_error_reporting(code):
"""Provide detailed error information."""
try:
module = astroid.parse(code)
return module
except astroid.AstroidSyntaxError as e:
# Chain with more context
raise astroid.AstroidBuildingError(f"Syntax error in code: {e}") from e
except Exception as e:
# Wrap unexpected errors
raise astroid.AstroidError(f"Unexpected error during parsing: {e}") from eInstall with Tessl CLI
npx tessl i tessl/pypi-astroid