CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-erdantic

Entity relationship diagrams for Python data model classes like Pydantic.

Pending
Overview
Eval results
Files

exceptions.mddocs/

Exception Classes

Erdantic defines several exception classes that provide specific error information when operations fail. These exceptions help identify and troubleshoot issues with model analysis, plugin registration, and diagram generation.

Exception Hierarchy

class ErdanticException(Exception):
    """Base class for all exceptions from erdantic library."""

class UnknownModelTypeError(ValueError, ErdanticException):
    """Raised when a given model does not match known model types from loaded plugins.

    Attributes:
        model (type): The model class that was not recognized.
        available_plugins (list[str]): List of plugin keys that were available.
    """

class PluginNotFoundError(KeyError, ErdanticException):
    """Raised when specified plugin key does not match a registered plugin.

    Attributes:
        key (str): The plugin key that was not found.
    """

class ModelOrModuleNotFoundError(ImportError, ErdanticException):
    """Raised when specified fully qualified name of model class or module cannot be imported."""

class UnresolvableForwardRefError(NameError, ErdanticException):
    """Raised when a forward reference in a type annotation cannot be resolved automatically.

    Attributes:
        name (str): The string representation of the unresolvable forward reference.
        model_full_name (FullyQualifiedName): The fully qualified name of the model with the forward reference.
    """

class UnevaluatedForwardRefError(ErdanticException):
    """Raised when a field's type declaration has an unevaluated forward reference.

    Attributes:
        model_full_name (FullyQualifiedName): The fully qualified name of the model with the field
            with the unevaluated forward reference.
        field_name (str): The name of the field with the unevaluated forward reference.
        forward_ref (str): The string representation of the unevaluated forward reference.
    """

class FieldNotFoundError(AttributeError, ErdanticException):
    """Raised trying to access a field name that does not match any fields returned by the
    field extractor function for a model.

    Attributes:
        name (str): The name of the field that was not found.
        obj (object): The model object that the field was being accessed on.
        model_full_name (FullyQualifiedName): The fully qualified name of the model.
    """

Required Imports

from erdantic.exceptions import (
    ErdanticException, UnknownModelTypeError, PluginNotFoundError,
    ModelOrModuleNotFoundError, UnresolvableForwardRefError,
    UnevaluatedForwardRefError, FieldNotFoundError
)
from erdantic.core import FullyQualifiedName

Usage Examples

Handling Model Type Errors

from erdantic import create
from erdantic.exceptions import UnknownModelTypeError

class MyCustomClass:
    """Not a data model class - will cause error."""
    name: str

try:
    diagram = create(MyCustomClass)
except UnknownModelTypeError as e:
    print(f"Model not recognized: {e.model}")
    print(f"Available plugins: {e.available_plugins}")
    print("Make sure your class inherits from a supported data model base class")

Handling Plugin Errors

from erdantic.plugins import get_predicate_fn
from erdantic.exceptions import PluginNotFoundError

try:
    predicate = get_predicate_fn("nonexistent_plugin")
except PluginNotFoundError as e:
    print(f"Plugin '{e.key}' not found")
    
    # Show available plugins
    from erdantic import list_plugins
    print(f"Available plugins: {list_plugins()}")

Handling Import Errors

from erdantic.cli import import_object_from_name
from erdantic.exceptions import ModelOrModuleNotFoundError

try:
    model_class = import_object_from_name("nonexistent.module.Model")
except ModelOrModuleNotFoundError as e:
    print(f"Could not import: {e}")
    print("Check that the module path is correct and the module is installed")

Handling Forward Reference Errors

from erdantic import create
from erdantic.exceptions import UnresolvableForwardRefError, UnevaluatedForwardRefError

try:
    diagram = create(MyModelWithForwardRefs)
except UnresolvableForwardRefError as e:
    print(f"Cannot resolve forward reference '{e.name}' in model {e.model_full_name}")
    print("Make sure all referenced types are properly imported or defined")
except UnevaluatedForwardRefError as e:
    print(f"Unevaluated forward reference '{e.forward_ref}' in field '{e.field_name}'")
    print(f"Model: {e.model_full_name}")
    print("This usually indicates a plugin issue - consider reporting as a bug")

Handling Field Access Errors

from erdantic.core import FieldInfo, FullyQualifiedName
from erdantic.exceptions import FieldNotFoundError

# This would occur when accessing field information programmatically
try:
    # Simulate field access that fails
    field_info = FieldInfo(
        model_full_name=FullyQualifiedName.from_object(MyModel),
        name="nonexistent_field",
        type_name="str"
    )
    raw_type = field_info.raw_type  # This accesses the field
except FieldNotFoundError as e:
    print(f"Field '{e.name}' not found on model {e.model_full_name}")
    print("Check that the field name is correct")

Comprehensive Error Handling

from erdantic import draw
from erdantic.exceptions import (
    ErdanticException, UnknownModelTypeError, PluginNotFoundError,
    ModelOrModuleNotFoundError, UnresolvableForwardRefError,
    UnevaluatedForwardRefError, FieldNotFoundError
)

def safe_draw_diagram(models_or_modules, output_path):
    """Draw diagram with comprehensive error handling."""
    try:
        draw(*models_or_modules, out=output_path)
        print(f"Diagram successfully created: {output_path}")
        
    except UnknownModelTypeError as e:
        print(f"❌ Unknown model type: {e.model.__name__}")
        print(f"   Available plugins: {e.available_plugins}")
        return False
        
    except PluginNotFoundError as e:
        print(f"❌ Plugin not found: {e.key}")
        return False
        
    except ModelOrModuleNotFoundError as e:
        print(f"❌ Import error: {e}")
        return False
        
    except (UnresolvableForwardRefError, UnevaluatedForwardRefError) as e:
        print(f"❌ Forward reference error: {e}")
        return False
        
    except FieldNotFoundError as e:
        print(f"❌ Field access error: {e}")
        return False
        
    except ErdanticException as e:
        print(f"❌ Erdantic error: {type(e).__name__}: {e}")
        return False
        
    except Exception as e:
        print(f"❌ Unexpected error: {type(e).__name__}: {e}")
        return False
        
    return True

# Usage
success = safe_draw_diagram([MyModel1, MyModel2], "diagram.png")
if not success:
    print("See error messages above for troubleshooting guidance")

Error Recovery Strategies

from erdantic import create, list_plugins
from erdantic.exceptions import UnknownModelTypeError, PluginNotFoundError

def create_diagram_with_fallback(models):
    """Create diagram with fallback strategies for common errors."""
    
    # Strategy 1: Try creating diagram normally
    try:
        return create(*models)
    except UnknownModelTypeError as e:
        print(f"Model {e.model} not supported by current plugins")
        
        # Strategy 2: Check if we need additional plugins
        available = e.available_plugins
        if "attrs" not in available:
            print("Consider installing: pip install attrs")
        if "msgspec" not in available:
            print("Consider installing: pip install msgspec")
            
        # Strategy 3: Filter to only supported models
        supported_models = []
        for model in models:
            try:
                create(model)  # Test individual model
                supported_models.append(model)
            except UnknownModelTypeError:
                print(f"Skipping unsupported model: {model.__name__}")
                
        if supported_models:
            print(f"Creating diagram with {len(supported_models)} supported models")
            return create(*supported_models)
        else:
            print("No supported models found")
            return None

# Usage
diagram = create_diagram_with_fallback([Model1, Model2, UnsupportedModel])
if diagram:
    diagram.draw("filtered_diagram.png")

Common Error Scenarios

Plugin Installation Issues

When erdantic cannot find support for your model types:

# Error: UnknownModelTypeError with attrs model
# Solution: pip install attrs

# Error: UnknownModelTypeError with msgspec model  
# Solution: pip install msgspec

# Error: All models show as unsupported
# Solution: Check that models inherit from proper base classes

Forward Reference Issues

When models contain forward references that cannot be resolved:

# Common causes:
# 1. Missing __future__ import: from __future__ import annotations
# 2. Circular imports between modules
# 3. Type hints referencing classes not yet defined
# 4. Missing imports for referenced types

# Solutions:
# 1. Add proper imports
# 2. Restructure to avoid circular dependencies
# 3. Use string literals for forward references
# 4. Ensure all referenced types are accessible

CLI Import Issues

When using the CLI with module or class paths:

# Error: ModelOrModuleNotFoundError
# Common causes:
# 1. Typo in module/class path
# 2. Module not installed or not in PYTHONPATH
# 3. Class doesn't exist in specified module

# Solutions:
# 1. Verify spelling and case sensitivity
# 2. Check module installation: python -c "import mymodule"
# 3. Check class exists: python -c "from mymodule import MyClass"

Install with Tessl CLI

npx tessl i tessl/pypi-erdantic

docs

cli.md

convenience-functions.md

diagram-creation.md

exceptions.md

index.md

model-info.md

plugin-system.md

tile.json