CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-erdantic

Entity relationship diagrams for Python data model classes like Pydantic.

Pending
Overview
Eval results
Files

convenience-functions.mddocs/

Convenience Functions

Erdantic provides high-level convenience functions for quick diagram generation without needing to manage EntityRelationshipDiagram instances directly. These functions automatically create diagrams, analyze models, and produce output in a single step.

Core Functions

def create(*models_or_modules: Union[type, ModuleType], terminal_models: Collection[type] = tuple(),
           termini: Collection[type] = tuple(), limit_search_models_to: Optional[Collection[str]] = None) -> EntityRelationshipDiagram:
    """Construct [`EntityRelationshipDiagram`][erdantic.core.EntityRelationshipDiagram] from given
    data model classes or modules.

    Args:
        *models_or_modules (type | ModuleType): Data model classes to add to diagram, or modules
            to search for data model classes.
        terminal_models (Collection[type]): Data model classes to set as terminal nodes. erdantic
            will stop searching for component classes when it reaches these models
        termini (Collection[type]): Deprecated. Use `terminal_models` instead.
        limit_search_models_to (Collection[str] | None): Plugin identifiers to limit to when
            searching modules for data model classes. Defaults to None which will not impose any
            limits.

    Returns:
        EntityRelationshipDiagram: diagram object for given data model.

    Raises:
        UnknownModelTypeError: if a given model does not match any model types from loaded plugins.
        UnresolvableForwardRefError: if a model contains a forward reference that cannot be
            automatically resolved.
    """

def draw(*models_or_modules: Union[type, ModuleType], out: Union[str, os.PathLike],
         terminal_models: Collection[type] = tuple(), termini: Collection[type] = tuple(),
         limit_search_models_to: Optional[Collection[str]] = None,
         graph_attr: Optional[Mapping[str, Any]] = None, node_attr: Optional[Mapping[str, Any]] = None,
         edge_attr: Optional[Mapping[str, Any]] = None, **kwargs):
    """Render entity relationship diagram for given data model classes to file.

    Args:
        *models_or_modules (type | ModuleType): Data model classes to add to diagram, or modules
            to search for data model classes.
        out (str | os.PathLike): Output file path for rendered diagram.
        terminal_models (Collection[type]): Data model classes to set as terminal nodes. erdantic
            will stop searching for component classes when it reaches these models
        termini (Collection[type]): Deprecated. Use `terminal_models` instead.
        limit_search_models_to (Optional[Collection[str]]): Plugin identifiers to limit to when
            searching modules for data model classes. Defaults to None which will not impose any
            limits.
        graph_attr (Mapping[str, Any] | None, optional): Override any graph attributes on
            the `pygraphviz.AGraph` instance. Defaults to None.
        node_attr (Mapping[str, Any] | None, optional): Override any node attributes for all
            nodes on the `pygraphviz.AGraph` instance. Defaults to None.
        edge_attr (Mapping[str, Any] | None, optional): Override any edge attributes for all
            edges on the `pygraphviz.AGraph` instance. Defaults to None.
        **kwargs: Additional keyword arguments to
            [`pygraphviz.AGraph.draw`][pygraphviz.AGraph.draw].

    Raises:
        UnknownModelTypeError: if a given model does not match any model types from loaded plugins.
        UnresolvableForwardRefError: if a model contains a forward reference that cannot be
            automatically resolved.
    """

def to_dot(*models_or_modules: Union[type, ModuleType], terminal_models: Collection[type] = [],
           termini: Collection[type] = tuple(), limit_search_models_to: Optional[Collection[str]] = None,
           graph_attr: Optional[Mapping[str, Any]] = None, node_attr: Optional[Mapping[str, Any]] = None,
           edge_attr: Optional[Mapping[str, Any]] = None) -> str:
    """Generate Graphviz [DOT language](https://graphviz.org/doc/info/lang.html) representation of
    entity relationship diagram for given data model classes.

    Args:
        *models_or_modules (type | ModuleType): Data model classes to add to diagram, or modules
            to search for data model classes.
        terminal_models (Collection[type]): Data model classes to set as terminal nodes. erdantic
            will stop searching for component classes when it reaches these models
        termini (Collection[type]): Deprecated. Use `terminal_models` instead.
        limit_search_models_to (Optional[Collection[str]]): Plugin identifiers to limit to when
            searching modules for data model classes. Defaults to None which will not impose any
            limits.
        graph_attr (Mapping[str, Any] | None, optional): Override any graph attributes on
            the `pygraphviz.AGraph` instance. Defaults to None.
        node_attr (Mapping[str, Any] | None, optional): Override any node attributes for all
            nodes on the `pygraphviz.AGraph` instance. Defaults to None.
        edge_attr (Mapping[str, Any] | None, optional): Override any edge attributes for all
            edges on the `pygraphviz.AGraph` instance. Defaults to None.

    Returns:
        str: DOT language representation of diagram
    """

def find_models(module: ModuleType, limit_search_models_to: Optional[Collection[str]] = None) -> Iterator[type]:
    """Searches a module and yields all data model classes found.

    Args:
        module (ModuleType): Module to search for data model classes.
        limit_search_models_to (Collection[str] | None): Plugin identifiers to limit to when
            searching modules for data model classes. Defaults to None which will not impose any
            limits.

    Yields:
        Iterator[type]: Members of module that are data model classes.

    Raises:
        UnknownModelTypeError: if a given model does not match any model types from loaded plugins.
        UnresolvableForwardRefError: if a model contains a forward reference that cannot be
            automatically resolved.
    """

Required Imports

from erdantic import create, draw, to_dot, find_models, list_plugins
from types import ModuleType
from typing import Union, Collection, Optional, Mapping, Any, Iterator
import os

Usage Examples

Quick Diagram Generation

from pydantic import BaseModel
from erdantic import draw

class User(BaseModel):
    name: str
    email: str

class Post(BaseModel):
    title: str
    author: User

# Generate diagram directly from model classes
draw(User, Post, out="quick_diagram.png")

Creating Diagram Objects

from erdantic import create

# Create a diagram object for further manipulation
diagram = create(User, Post)

# Now you can use diagram methods
diagram.draw("output.svg")
dot_content = diagram.to_dot()

Working with Modules

import my_models_module
from erdantic import draw

# Analyze entire module for data model classes
draw(my_models_module, out="module_diagram.png")

# Limit search to specific plugin types
draw(my_models_module, out="pydantic_only.png", limit_search_models_to=["pydantic"])

Terminal Models

from erdantic import draw

class BaseEntity(BaseModel):
    id: int
    created_at: datetime

class User(BaseEntity):
    name: str
    email: str

class Post(BaseEntity):
    title: str
    author: User

# Stop analysis at BaseEntity - don't recurse into its fields
draw(User, Post, terminal_models=[BaseEntity], out="with_terminal.png")

Advanced Styling

from erdantic import draw

# Custom graph appearance
graph_style = {
    "rankdir": "TB",  # Top-to-bottom layout
    "bgcolor": "lightgray",
    "label": "My Application Models"
}

node_style = {
    "fillcolor": "lightblue",
    "style": "filled,rounded",
    "fontname": "Arial"
}

edge_style = {
    "color": "darkblue",
    "penwidth": 2
}

draw(
    User, Post,
    out="styled_diagram.svg",
    graph_attr=graph_style,
    node_attr=node_style,
    edge_attr=edge_style
)

DOT Generation

from erdantic import to_dot

# Generate DOT language representation
dot_string = to_dot(User, Post)
print(dot_string)

# Save for external processing
with open("models.dot", "w") as f:
    f.write(dot_string)

# Generate with custom attributes
custom_dot = to_dot(
    User, Post,
    graph_attr={"rankdir": "TD"},
    node_attr={"shape": "box"}
)

Module Model Discovery

from erdantic import find_models
import my_models_module

# Find all supported models in a module
models = list(find_models(my_models_module))
print(f"Found {len(models)} model classes: {[m.__name__ for m in models]}")

# Find only specific model types
pydantic_models = list(find_models(my_models_module, limit_search_models_to=["pydantic"]))
dataclass_models = list(find_models(my_models_module, limit_search_models_to=["dataclasses"]))

# Use discovered models directly
from erdantic import draw
draw(*models, out="all_discovered_models.png")

Plugin Limitation

from erdantic import draw, list_plugins

# See available plugins
print("Available plugins:", list_plugins())

# Generate diagrams for specific model types only
draw(my_module, out="pydantic_models.png", limit_search_models_to=["pydantic"])
draw(my_module, out="dataclass_models.png", limit_search_models_to=["dataclasses"])
draw(my_module, out="attrs_models.png", limit_search_models_to=["attrs"])

Error Handling

from erdantic import draw
from erdantic.exceptions import UnknownModelTypeError, UnresolvableForwardRefError

try:
    draw(MyModel, out="diagram.png")
except UnknownModelTypeError as e:
    print(f"Model type not supported: {e.model}")
    print(f"Available plugins: {e.available_plugins}")
except UnresolvableForwardRefError as e:
    print(f"Cannot resolve forward reference '{e.name}' in model {e.model_full_name}")
except FileNotFoundError as e:
    print(f"Output directory does not exist: {e}")

Comparison with Direct Diagram Usage

Convenience Functions (Recommended for Simple Cases)

# One-liner diagram generation
draw(User, Post, out="simple.png")

Direct Diagram Usage (More Control)

# Multi-step with more control options
diagram = EntityRelationshipDiagram()
diagram.add_model(User)
diagram.add_model(Post)
diagram.draw("controlled.png")

# Access to diagram data
print(f"Models analyzed: {len(diagram.models)}")
print(f"Relationships found: {len(diagram.edges)}")

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