### Install erdantic with pip Source: https://github.com/drivendataorg/erdantic/blob/main/README.md Install erdantic and its Python dependencies from PyPI after ensuring Graphviz is installed separately. ```bash pip install erdantic ``` -------------------------------- ### Install erdantic development version Source: https://github.com/drivendataorg/erdantic/blob/main/README.md Install the latest development version of erdantic directly from its GitHub repository using pip. ```bash pip install "erdantic @ git+https://github.com/drivendataorg/erdantic.git" ``` -------------------------------- ### Install erdantic Source: https://context7.com/drivendataorg/erdantic/llms.txt Install erdantic using conda or pip. For pip, Graphviz must be pre-installed. Optional extras are available for attrs and msgspec support. ```bash conda install erdantic -c conda-forge ``` ```bash pip install erdantic ``` ```bash pip install "erdantic[attrs,msgspec]" ``` -------------------------------- ### Registering a Custom Modeling Framework Plugin Source: https://context7.com/drivendataorg/erdantic/llms.txt Provides an example of how to register a custom plugin for a hypothetical 'MyModel' base class. This involves defining predicate and extractor functions and then registering them with `register_plugin`. ```python from typing import Any import erdantic from erdantic.core import FieldInfo, FullyQualifiedName from erdantic.plugins import register_plugin # Example: plugin for a hypothetical "MyModel" base class class MyModel: _fields: dict # hypothetical field registry def is_my_model(obj: Any) -> bool: """Predicate: returns True if obj is a subclass of MyModel.""" return isinstance(obj, type) and issubclass(obj, MyModel) def get_fields_from_my_model(model: type) -> list[FieldInfo]: """Extractor: returns a FieldInfo for each declared field.""" fqn = FullyQualifiedName.from_object(model) return [ FieldInfo.from_raw_type( model_full_name=fqn, name=name, raw_type=raw_type, ) for name, raw_type in model.__annotations__.items() ] # Register the plugin under a unique key register_plugin( key="my_model", predicate_fn=is_my_model, get_fields_fn=get_fields_from_my_model, ) # Verify it appears print(erdantic.list_plugins()) # ['pydantic', 'attrs', 'dataclasses', 'msgspec', 'pydantic_v1', 'my_model'] # Now erdantic.create / erdantic.draw will automatically handle MyModel subclasses class MyChildModel(MyModel): items: list # annotation that erdantic can pick up # diagram = erdantic.create(MyChildModel) ``` -------------------------------- ### Install erdantic with conda Source: https://github.com/drivendataorg/erdantic/blob/main/README.md Use conda to install erdantic and its dependencies, including Graphviz, from the conda-forge channel. ```bash conda install erdantic -c conda-forge ``` -------------------------------- ### Define Quest Class with attrs Source: https://github.com/drivendataorg/erdantic/blob/main/docs/notebooks/examples/attrs.ipynb Defines a Quest class using attrs. This serves as a basic example of class definition. ```python @define class Quest: pass ``` -------------------------------- ### Define a Dataclass for Quest Source: https://github.com/drivendataorg/erdantic/blob/main/docs/notebooks/examples/dataclasses.ipynb Defines a simple dataclass named Quest. This serves as a basic example of a dataclass structure. ```python @dataclass class Quest: pass ``` -------------------------------- ### DOT Language Representation Example Source: https://github.com/drivendataorg/erdantic/blob/main/docs/notebooks/examples/pydantic.ipynb This is the DOT language output generated by erdantic for the Pydantic models, which Graphviz uses to create diagrams. ```dot digraph "Entity Relationship Diagram created by erdantic" { graph [fontcolor=gray66, fontname="Times New Roman,Times,Liberation Serif,serif", fontsize=9, label="Created by erdantic v1.0.0.dev0 ", nodesep=0.5, rankdir=LR, ranksep=1.5 ]; node [fontname="Times New Roman,Times,Liberation Serif,serif", fontsize=14, label="\N", shape=plain ]; edge [dir=both]; "erdantic.examples.pydantic.Adventurer" [label=<
Adventurer
namestr
professionstr
levelint
alignmentAlignment
>, tooltip="erdantic.examples.pydantic.Adventurer A person often late for dinner but with a tale or two to tell. Attributes:&#\xA; name (str): Name of this adventurer profession (str): Profession of this adventurer level (int): Level of \nthis adventurer alignment (Alignment): Alignment of this adventurer "]; "erdantic.examples.pydantic.Party" [label=<
Party
namestr
formed_datetimedatetime
membersList[Adventurer]
active_questOptional[Quest]
>, tooltip="erdantic.examples.pydantic.Party A group of adventurers finding themselves doing and saying things altogether unexpected.&#\xA; Attributes: name (str): Name that party is known by formed_datetime (datetime): Timestamp of when the party \nwas formed members (List[Adventurer]): Adventurers that belong to this party active_quest (Optional[Quest]): Current \nquest that party is actively tackling "]; "erdantic.examples.pydantic.Party":members:e -> "erdantic.examples.pydantic.Adventurer":_root:w [arrowhead=crownone, arrowtail=nonenone]; "erdantic.examples.pydantic.Quest" [label=<
Quest
namestr
giverQuestGiver
reward_goldint
>, tooltip="erdantic.examples.pydantic.Quest A task to complete, with some monetary reward. Attributes: name (str): \nName by which this quest is referred to giver (QuestGiver): Person who offered the quest reward_gold (int): Amount \nof gold to be rewarded for quest completion "]; "erdantic.examples.pydantic.Party":active_quest:e -> "erdantic.examples.pydantic.Quest":_root:w [arrowhead=noneteeodot, arrowtail=nonenone]; "erdantic.examples.pydantic.QuestGiver" [label=<
QuestGiver
namestr
factionOptional[str]
locationstr
>, tooltip="erdantic.examples.pydantic.QuestGiver A person who offers a task that needs completing. Attributes: name (str): \nName of this quest giver faction (str): Faction that this quest giver belongs to location (str): Location \nthis quest giver can be found "]; "erdantic.examples.pydantic.Quest":giver:e -> "erdantic.examples.pydantic.QuestGiver":_root:w [arrowhead=noneteetee, arrowtail=nonenone]; } ``` -------------------------------- ### Create and Display Diagram with Erdantic Source: https://github.com/drivendataorg/erdantic/blob/main/docs/notebooks/examples/attrs.ipynb Use the erdantic.create function to generate a diagram object from a model. The diagram object automatically pretty-prints and renders in IPython/Jupyter environments. Ensure the 'rich' library is installed for colored output. ```python import erdantic as erd from erdantic.examples.attrs import Party diagram = erd.create(Party) diagram ``` -------------------------------- ### DOT Language Representation Example Source: https://github.com/drivendataorg/erdantic/blob/main/docs/notebooks/examples/dataclasses.ipynb This is the DOT language output generated by erdantic, which describes the entity relationships. ```dot digraph "Entity Relationship Diagram created by erdantic" { graph [fontcolor=gray66, fontname="Times New Roman,Times,Liberation Serif,serif", fontsize=9, label="Created by erdantic v1.0.0.dev0 ", nodesep=0.5, rankdir=LR, ranksep=1.5 ]; node [fontname="Times New Roman,Times,Liberation Serif,serif", fontsize=14, label="\N", shape=plain ]; edge [dir=both]; "erdantic.examples.dataclasses.Adventurer" [label=<
Adventurer
namestr
professionstr
levelint
alignmentAlignment
>, tooltip="erdantic.examples.dataclasses.Adventurer A person often late for dinner but with a tale or two to tell. Attributes:&#\n; name (str): Name of this adventurer profession (str): Profession of this adventurer level (int): Level of this adventurer alignment (Alignment): Alignment of this adventurer "]; "erdantic.examples.dataclasses.Party" [label=<
Party
namestr
formed_datetimedatetime
membersList[Adventurer]
active_questOptional[Quest]
>, tooltip="erdantic.examples.dataclasses.Party A group of adventurers finding themselves doing and saying things altogether unexpected.&#\n;A; name (str): Name that party is known by formed_datetime (datetime): Timestamp of when the party was formed members (List[Adventurer]): Adventurers that belong to this party active_quest (Optional[Quest]): Current quest that party is actively tackling "]; "erdantic.examples.dataclasses.Party":members:e -> "erdantic.examples.dataclasses.Adventurer":_root:w [arrowhead=crownone, arrowtail=nonenone]; "erdantic.examples.dataclasses.Quest" [label=<
Quest
namestr
giverQuestGiver
reward_goldint
>, tooltip="erdantic.examples.dataclasses.Quest A task to complete, with some monetary reward. Attributes: name (str): Name by which this quest is referred to giver (QuestGiver): Person who offered the quest reward_gold (int): Amount of gold to be rewarded for quest completion "]; "erdantic.examples.dataclasses.Party":active_quest:e -> "erdantic.examples.dataclasses.Quest":_root:w [arrowhead=noneteeodot, arrowtail=nonenone]; "erdantic.examples.dataclasses.QuestGiver" [label=<
QuestGiver
namestr
factionOptional[str]
locationstr
>, tooltip="erdantic.examples.dataclasses.QuestGiver A person who offers a task that needs completing. Attributes: name (str): Name of this quest giver faction (str): Faction that this quest giver belongs to location (str): Location this quest giver can be found "]; "erdantic.examples.dataclasses.Quest":giver:e -> "erdantic.examples.dataclasses.QuestGiver":_root:w [arrowhead=noneteetee, arrowtail=nonenone]; } ``` -------------------------------- ### Create and Inspect Diagram Object Source: https://github.com/drivendataorg/erdantic/blob/main/docs/notebooks/examples/pydantic.ipynb Use `erd.create()` to generate a diagram object from a Pydantic model. The diagram object pretty-prints in IPython/Jupyter and automatically renders in notebooks if `rich` is installed. ```python import erdantic as erd from erdantic.examples.pydantic import Party diagram = erd.create(Party) diagram ``` -------------------------------- ### Create and Inspect Diagram Object Source: https://github.com/drivendataorg/erdantic/blob/main/docs/notebooks/examples/dataclasses.ipynb Use `erd.create()` to generate a diagram object from a dataclass. The diagram object automatically pretty-prints and renders in IPython/Jupyter environments. Install the `rich` library for colored output. ```python import erdantic as erd from erdantic.examples.dataclasses import Party diagram = erd.create(Party) diagram ``` -------------------------------- ### Get DOT Representation of Diagram Source: https://github.com/drivendataorg/erdantic/blob/main/docs/notebooks/examples/msgspec.ipynb Obtains the DOT language representation of the diagram as a string using the `to_dot` method. ```python print(diagram.to_dot()) # Equivalently, use erd.to_dot directly from Party assert diagram.to_dot() == erd.to_dot(Party) ``` -------------------------------- ### Add Default Field Values Column to Diagram Source: https://github.com/drivendataorg/erdantic/blob/main/docs/docs/extending.md This example demonstrates how to modify Pydantic model handling to extract and display default field values as a third column in the diagram. ```python from typing import Any, Dict, List, Optional, Tuple from erdantic.core import ( # noqa EntityRelationshipDiagram, FieldInfo, ModelInfo, erdantic_version ) from erdantic.examples.pydantic import Party class CustomFieldInfo(FieldInfo): @classmethod def from_raw_type(cls, model_info: ModelInfo, name: str, raw_type: Any) -> "FieldInfo": field_info = super().from_raw_type(model_info, name, raw_type) if field_info.default is not None: field_info.default = repr(field_info.default) return field_info def to_dot_row(self) -> Tuple[str, str, str]: return ( self.name, str(self.type), self.default if self.default is not None else "", ) class CustomModelInfo(ModelInfo): @classmethod def from_raw_model(cls, raw_model: Any) -> "ModelInfo": model_info = super().from_raw_model(raw_model) model_info.fields = sorted( [CustomFieldInfo.from_raw_type(model_info, name, raw_type) for name, raw_type in model_info.fields_raw], key=lambda x: x.name, ) return model_info def to_dot_label(self) -> str: rows: List[Tuple[str, str, str]] = [self.to_dot_row()] rows.extend([field.to_dot_row() for field in self.fields]) return ( f"< " + "\n".join([f'' for name, type_, default in rows[1:]]) + "
{self.name}
NameTypeDefault
{name}{type_}{default}
" ) class CustomEntityRelationshipDiagram(EntityRelationshipDiagram): models: Dict[str, ModelInfo] = {} # type: ignore edges: List[Any] = [] # type: ignore def __init__(self, **kwargs: Any) -> None: super().__init__(**kwargs) self.models = {} # type: ignore self.edges = [] # type: ignore @property def model_info_class(self) -> type[ModelInfo]: return CustomModelInfo @property def field_info_class(self) -> type[FieldInfo]: return CustomFieldInfo diagram = CustomEntityRelationshipDiagram() diagram.add_model(Party) diagram.draw("pydantic_with_default_column_diagram.png") print(f"Erdantic version: {erdantic_version}") ``` -------------------------------- ### View available Just recipes Source: https://github.com/drivendataorg/erdantic/blob/main/CONTRIBUTING.md Run this command to see a list of available tasks and their descriptions defined in the Justfile. ```bash just ``` -------------------------------- ### View CLI Help Documentation Source: https://github.com/drivendataorg/erdantic/blob/main/docs/docs/cli.md Run this command to display the full help documentation for the erdantic CLI. This is useful for understanding all available commands and options. ```bash erdantic --help ``` ```bash python -m erdantic --help ``` -------------------------------- ### Listing and Using Registered Plugins Source: https://context7.com/drivendataorg/erdantic/llms.txt Demonstrates how to list the keys of all currently registered plugins using `erdantic.list_plugins`. It also shows how to use a plugin key to restrict a module-wide search when creating a diagram. ```python import erdantic plugins = erdantic.list_plugins() print(plugins) # ['pydantic', 'attrs', 'dataclasses', 'msgspec', 'pydantic_v1'] # Use a plugin key to restrict module-wide search import erdantic.examples.pydantic as mod diagram = erdantic.create(mod, limit_search_models_to=["pydantic"]) print(list(diagram.models.keys())) # ['erdantic.examples.pydantic.Adventurer', 'erdantic.examples.pydantic.Party', # 'erdantic.examples.pydantic.Quest', 'erdantic.examples.pydantic.QuestGiver'] ``` -------------------------------- ### Activate Pixi development environment Source: https://github.com/drivendataorg/erdantic/blob/main/CONTRIBUTING.md Enter the default development shell provided by Pixi. ```bash pixi shell ``` -------------------------------- ### Working with FullyQualifiedName Source: https://context7.com/drivendataorg/erdantic/llms.txt Illustrates how to create FullyQualifiedName objects from live Python objects, reconstruct them from module and qual_name, and import the live class object. It also shows that FullyQualifiedName instances are sortable and hashable. ```python from erdantic.core import FullyQualifiedName from erdantic.examples.pydantic import Party # Create from a live object fqn = FullyQualifiedName.from_object(Party) print(fqn.module) # 'erdantic.examples.pydantic' print(fqn.qual_name) # 'Party' print(str(fqn)) # 'erdantic.examples.pydantic.Party' # Reconstruct from JSON fqn2 = FullyQualifiedName( module="erdantic.examples.pydantic", qual_name="Party", ) # Re-import the live class from a FullyQualifiedName cls = fqn2.import_object() print(cls) # # FullyQualifiedName instances are sortable and hashable names = [FullyQualifiedName.from_object(c) for c in [Party]] print(sorted(names)) ``` -------------------------------- ### Run linter with Just Source: https://github.com/drivendataorg/erdantic/blob/main/CONTRIBUTING.md Execute the linter (Ruff) to check code quality and formatting. ```bash just lint ``` -------------------------------- ### Run tests with Just Source: https://github.com/drivendataorg/erdantic/blob/main/CONTRIBUTING.md Execute the test suite using the Just task runner. ```bash just test ``` -------------------------------- ### Run tests on all supported Python versions Source: https://github.com/drivendataorg/erdantic/blob/main/CONTRIBUTING.md Execute the test suite across all Python versions configured for the project. ```bash just test-all ``` -------------------------------- ### CLI: Draw diagram from model Source: https://context7.com/drivendataorg/erdantic/llms.txt Use the CLI to render an ERD from one or more root model classes. Output format is inferred from the file extension. Use --dot or --d2 to print language to stdout. ```bash erdantic erdantic.examples.pydantic.Party -o diagram.png ``` ```bash erdantic erdantic.examples.pydantic.Party -o diagram.svg ``` ```bash erdantic myapp.models.Order myapp.models.Customer -o schema.png ``` ```bash erdantic myapp.models.Order --terminal-model myapp.models.Address -o order.png ``` ```bash erdantic myapp.models -o all_models.png ``` ```bash erdantic erdantic.examples.pydantic.Party --dot ``` ```bash erdantic erdantic.examples.pydantic.Party --d2 ``` ```bash erdantic erdantic.examples.pydantic.Party -o diagram.png --no-overwrite ``` ```bash erdantic myapp.models -o pydantic_only.png --limit-search-models-to pydantic ``` ```bash erdantic --list-plugins ``` ```bash erdantic --version ``` -------------------------------- ### Run tests with arguments Source: https://github.com/drivendataorg/erdantic/blob/main/CONTRIBUTING.md Pass arguments to the test runner, such as specifying a particular test file. ```bash just test-all tests/test_against_assets.py ``` -------------------------------- ### CLI Usage: Draw a diagram from the command line Source: https://context7.com/drivendataorg/erdantic/llms.txt Renders an ERD for one or more root model classes. Output format is inferred from the file extension. Supports various options for output format, recursion control, and outputting DOT/D2 language. ```APIDOC ## CLI Usage: Draw a diagram from the command line Renders an ERD for one or more root model classes (erdantic traverses the composition tree automatically). Output format is inferred from the file extension. ### Examples ```bash # Render to PNG erdantic erdantic.examples.pydantic.Party -o diagram.png # Render to SVG erdantic erdantic.examples.pydantic.Party -o diagram.svg # Render multiple root models erdantic myapp.models.Order myapp.models.Customer -o schema.png # Use a terminal model to stop recursion at a boundary class erdantic myapp.models.Order --terminal-model myapp.models.Address -o order.png # Search an entire module for all data model classes erdantic myapp.models -o all_models.png # Print DOT language to stdout instead of rendering erdantic erdantic.examples.pydantic.Party --dot # Print D2 language to stdout erdantic erdantic.examples.pydantic.Party --d2 # Prevent overwriting an existing file erdantic erdantic.examples.pydantic.Party -o diagram.png --no-overwrite # Limit module search to a specific plugin type erdantic myapp.models -o pydantic_only.png --limit-search-models-to pydantic # List active plugins erdantic --list-plugins # Show version erdantic --version ``` ``` -------------------------------- ### Run commands in Pixi environment Source: https://github.com/drivendataorg/erdantic/blob/main/CONTRIBUTING.md Execute shell commands within the project's managed development environment. ```bash pixi run {some shell command} ``` -------------------------------- ### Run type checker with Just Source: https://github.com/drivendataorg/erdantic/blob/main/CONTRIBUTING.md Execute the static type checker (mypy) to verify type correctness. ```bash just typecheck ``` -------------------------------- ### Display attrs source code Source: https://github.com/drivendataorg/erdantic/blob/main/docs/notebooks/examples/attrs.ipynb Imports necessary libraries and displays the source code of attrs models using rich.syntax.Syntax for formatted output. ```python import inspect import rich.syntax import erdantic.examples.attrs rich.syntax.Syntax( inspect.getsource(erdantic.examples.attrs), "python", theme="default", line_numbers=True ) ``` -------------------------------- ### Accessing and Modifying Model Information Source: https://context7.com/drivendataorg/erdantic/llms.txt Demonstrates how to access individual field information, directly edit model descriptions, and retrieve the raw class object. Also shows how to serialize ModelInfo to JSON. ```python field = model_info.fields["members"] print(field.name) # 'members' print(field.type_name) # 'list[Adventurer]' # Directly edit the description (reflected in diagram tooltips) model_info.description = "My custom description for Party" # Retrieve the live class object raw_cls = model_info.raw_model print(raw_cls) # # Serialize a single ModelInfo import json print(json.dumps(model_info.model_dump(), indent=2)[:300]) ``` -------------------------------- ### Render Diagram using CLI Source: https://github.com/drivendataorg/erdantic/blob/main/docs/notebooks/examples/attrs.ipynb Use the `erdantic` CLI to generate a diagram from a Python class. Pass the full dotted path to the root class and the desired output file path. The file extension infers the output format. ```bash !erdantic erdantic.examples.attrs.Party -o diagram.png ``` -------------------------------- ### Create Second Diagram with Terminal Node (Python) Source: https://github.com/drivendataorg/erdantic/blob/main/docs/notebooks/examples/msgspec.ipynb Creates a second diagram rooted by a specified terminal model. ```python diagram2 = erd.create(Quest) diagram2 ``` -------------------------------- ### Run tests for a specific Python version Source: https://github.com/drivendataorg/erdantic/blob/main/CONTRIBUTING.md Run the test suite using a specific Python version managed by Pixi. ```bash just python=3.12 test ``` -------------------------------- ### Define QuestGiver Class with attrs Source: https://github.com/drivendataorg/erdantic/blob/main/docs/notebooks/examples/attrs.ipynb Defines a QuestGiver class with name, faction, and location attributes using attrs. Faction is an optional string. ```python class QuestGiver: """A person who offers a task that needs completing. Attributes: name (str): Name of this quest giver faction (str): Faction that this quest giver belongs to location (str): Location this quest giver can be found """ name: str faction: Optional[str] location: str ``` -------------------------------- ### Generate Diagram with Terminal Model (CLI) Source: https://github.com/drivendataorg/erdantic/blob/main/docs/notebooks/examples/attrs.ipynb Use the `-t` option in the CLI to specify models that should be treated as terminal nodes in the diagram. Multiple `-t` options can be used to specify multiple terminal models. ```bash erdantic erdantic.examples.attrs.Party \ -t erdantic erdantic.examples.attrs.Quest \ -o party.png erdantic erdantic.examples.attrs.Quest -o quest.png ``` -------------------------------- ### Generate Diagrams with Terminal Nodes (CLI) Source: https://github.com/drivendataorg/erdantic/blob/main/docs/notebooks/examples/pydantic.ipynb Use the `-t` option in the CLI to specify models that should be treated as terminal nodes in the generated diagram. Multiple `-t` options can be used to specify multiple terminal models. ```bash erdantic erdantic.examples.pydantic.Party \ -t erdantic erdantic.examples.pydantic.Quest \ -o party.png erdantic erdantic.examples.pydantic.Quest -o quest.png ``` -------------------------------- ### Render Diagram to Image File Source: https://github.com/drivendataorg/erdantic/blob/main/docs/notebooks/examples/msgspec.ipynb Renders the created diagram to an SVG image file using the `draw` method. ```python diagram.draw("diagram.svg") # Equivalently, use erd.draw directly from Party # erd.draw(Party, out="diagram.svg") ``` -------------------------------- ### Render Dataclass Diagram with CLI Source: https://github.com/drivendataorg/erdantic/blob/main/docs/notebooks/examples/dataclasses.ipynb Use the erdantic CLI to render a diagram from a Python dataclass. The output format is inferred from the file extension. Ensure the root class path and output file path are correctly specified. ```bash !erdantic erdantic.examples.dataclasses.Party -o diagram.png ``` -------------------------------- ### Generate Diagram using CLI Source: https://github.com/drivendataorg/erdantic/blob/main/docs/notebooks/examples/pydantic.ipynb Use the erdantic CLI to generate a diagram from a specified Python class. The output format is determined by the file extension provided. ```bash !erdantic erdantic.examples.pydantic.Party -o diagram.png ``` -------------------------------- ### Display Pydantic Model Source Code Source: https://github.com/drivendataorg/erdantic/blob/main/docs/notebooks/examples/pydantic.ipynb Imports the necessary libraries and displays the source code of Pydantic models from the erdantic.examples.pydantic module. ```python import inspect import rich.syntax import erdantic.examples.pydantic rich.syntax.Syntax( inspect.getsource(erdantic.examples.pydantic), "python", theme="default", line_numbers=True ) ``` -------------------------------- ### Generate Diagram via CLI Source: https://github.com/drivendataorg/erdantic/blob/main/docs/notebooks/examples/msgspec.ipynb Uses the erdantic CLI to generate a diagram from a msgspec struct, inferring the output format from the file extension. ```bash !erdantic erdantic.examples.msgspec.Party -o diagram.png ``` -------------------------------- ### Inspect Msgspec Structs Source: https://github.com/drivendataorg/erdantic/blob/main/docs/notebooks/examples/msgspec.ipynb Imports necessary libraries and displays the source code of msgspec structs for clarity. ```python import inspect import rich.syntax import erdantic.examples.msgspec rich.syntax.Syntax( inspect.getsource(erdantic.examples.msgspec), "python", theme="default", line_numbers=True ) ``` -------------------------------- ### Display Dataclass Source Code Source: https://github.com/drivendataorg/erdantic/blob/main/docs/notebooks/examples/dataclasses.ipynb Uses `inspect.getsource` and `rich.syntax.Syntax` to display the source code of dataclass models. This is useful for understanding the structure of the models being used. ```python import inspect import rich.syntax import erdantic.examples.dataclasses rich.syntax.Syntax( inspect.getsource(erdantic.examples.dataclasses), "python", theme="default", line_numbers=True ) ``` -------------------------------- ### Generate Diagrams with Terminal Nodes via CLI Source: https://github.com/drivendataorg/erdantic/blob/main/docs/notebooks/examples/msgspec.ipynb Uses the erdantic CLI with the `-t` option to specify terminal nodes, creating diagrams that terminate at specified models. ```bash erdantic erdantic.examples.msgspec.Party \ -t erdantic erdantic.examples.msgspec.Quest \ -o party.png erdantic erdantic.examples.msgspec.Quest -o quest.png ``` -------------------------------- ### Create Diagram with Terminal Nodes (Python) Source: https://github.com/drivendataorg/erdantic/blob/main/docs/notebooks/examples/msgspec.ipynb Uses the erdantic Python library to create a diagram, specifying terminal models using the `terminal_models` keyword argument. ```python from erdantic.examples.msgspec import Quest diagram1 = erd.create(Party, terminal_models=[Quest]) diagram1 ``` -------------------------------- ### EntityRelationshipDiagram Usage Source: https://context7.com/drivendataorg/erdantic/llms.txt Demonstrates basic usage of the EntityRelationshipDiagram class, including adding models and rendering the diagram to a file. ```APIDOC ## EntityRelationshipDiagram ### Description The core data container class (a Pydantic `BaseModel`) that holds all `ModelInfo` and `Edge` objects and provides rendering methods. Can be subclassed for advanced customization. ### Usage ```python from erdantic.core import EntityRelationshipDiagram from erdantic.examples.pydantic import Party, QuestGiver diagram = EntityRelationshipDiagram() # Add models manually with optional recursion control diagram.add_model(QuestGiver, recurse=False) # leaf only, no further traversal diagram.add_model(Party) # recurses into all composed models # Render to file (format inferred from extension: .png, .svg, .pdf, etc.) diagram.draw("diagram.png") # Override Graphviz attributes at render time diagram.draw( "diagram.svg", graph_attr={"ranksep": "2.0"}, node_attr={"fontsize": "11"}, ) # Get the underlying pygraphviz.AGraph for low-level manipulation agraph = diagram.to_graphviz() agraph.graph_attr["bgcolor"] = "lightyellow" agraph.draw("custom.png", prog="dot") # Get DOT language string dot = diagram.to_dot() # Get D2 language string d2 = diagram.to_d2() # Serialize to JSON json_data = diagram.model_dump_json() print(json_data[:200]) # Deserialize from JSON diagram2 = EntityRelationshipDiagram.model_validate_json(json_data) diagram2.draw("from_json.png") # Subclass to customize behavior class CustomDiagram(EntityRelationshipDiagram): def draw(self, out, **kwargs): # Custom pre-render hook print(f"Rendering {len(self.models)} models to {out}") super().draw(out, **kwargs) custom = CustomDiagram() custom.add_model(Party) custom.draw("custom_diagram.png") ``` ``` -------------------------------- ### ModelInfo: Metadata for Models Source: https://context7.com/drivendataorg/erdantic/llms.txt The `ModelInfo` class holds metadata for each analyzed Pydantic model, accessible through `diagram.models`. It provides access to the model's name, full name, description, and fields. ```python from erdantic.core import EntityRelationshipDiagram from erdantic.examples.pydantic import Party diagram = EntityRelationshipDiagram() diagram.add_model(Party) model_info = diagram.models["erdantic.examples.pydantic.Party"] print(model_info.name) # 'Party' print(str(model_info.full_name)) # 'erdantic.examples.pydantic.Party' print(model_info.description) # 'erdantic.examples.pydantic.Party\n\nA group of...' print(list(model_info.fields.keys())) # ['active_quest', 'formed_datetime', 'members', 'name'] ``` -------------------------------- ### Generate ERD from CLI Source: https://github.com/drivendataorg/erdantic/blob/main/README.md Use the erdantic CLI to generate a diagram by specifying the dotted import path of a model and an output file. The format is inferred from the filename extension. ```bash erdantic erdantic.examples.pydantic.Party -o diagram.png ``` -------------------------------- ### Generate Diagram with Terminal Model (Python) Source: https://github.com/drivendataorg/erdantic/blob/main/docs/notebooks/examples/attrs.ipynb When using the Python library, pass a list of terminal models to the `terminal_models` keyword argument in `erd.create()` to control diagram termination. ```python from erdantic.examples.attrs import Quest diagram1 = erd.create(Party, terminal_models=[Quest]) diagram1 ``` ```python diagram2 = erd.create(Quest) diagram2 ``` -------------------------------- ### Define a Dataclass for Quest Giver Source: https://github.com/drivendataorg/erdantic/blob/main/docs/notebooks/examples/dataclasses.ipynb Defines a dataclass named QuestGiver with attributes for name, faction, and location. The faction attribute is optional. ```python from dataclasses import dataclass from typing import Optional @dataclass class QuestGiver: """A person who offers a task that needs completing. Attributes: name (str): Name of this quest giver faction (str): Faction that this quest giver belongs to location (str): Location this quest giver can be found """ name: str faction: Optional[str] location: str ``` -------------------------------- ### Python API: erdantic.draw Source: https://context7.com/drivendataorg/erdantic/llms.txt One-shot convenience function that creates a diagram and renders it to a file in a single call. Supports multiple root models, terminal models for recursion control, and customization of Graphviz attributes. ```APIDOC ## Python API: erdantic.draw One-shot convenience function that creates a diagram and renders it to a file in a single call. ### Usage ```python import erdantic from erdantic.examples.pydantic import Party # Simplest usage: renders Party and all composed models into a PNG erdantic.draw(Party, out="diagram.png") # Multiple root models from erdantic.examples.pydantic import Quest, Party erdantic.draw(Party, Quest, out="diagram.svg") # Stop recursion at a terminal model so it appears as a leaf node from erdantic.examples.pydantic import Party, QuestGiver erdantic.draw(Party, out="party_limited.png", terminal_models=[QuestGiver]) # Customize Graphviz attributes erdantic.draw( Party, out="diagram.png", graph_attr={"nodesep": "1.0", "ranksep": "2.0"}, node_attr={"fontsize": "12"}, edge_attr={"color": "blue"}, ) # Search an entire module import erdantic.examples.pydantic as pydantic_examples erdantic.draw(pydantic_examples, out="all_pydantic.png") ``` ``` -------------------------------- ### Generate D2 Output via CLI Source: https://github.com/drivendataorg/erdantic/blob/main/docs/notebooks/output-formats/d2.ipynb Use the `--d2` flag with the erdantic CLI to generate D2 language output. This is useful for quick diagram generation from the command line. ```bash !erdantic erdantic.examples.pydantic.Party --d2 ``` -------------------------------- ### Create Diagram with Python Library Source: https://github.com/drivendataorg/erdantic/blob/main/docs/notebooks/examples/msgspec.ipynb Uses the erdantic Python library to create a diagram object from a msgspec struct. The diagram object pretty-prints and automatically renders in Jupyter notebooks. ```python import erdantic as erd from erdantic.examples.msgspec import Party diagram = erd.create(Party) diagram ``` -------------------------------- ### Generate Diagram with Terminal Node (Python) Source: https://github.com/drivendataorg/erdantic/blob/main/docs/notebooks/examples/pydantic.ipynb When using the Python library, pass terminal models as a list to the `terminal_models` keyword argument of the `erd.create` function. ```python from erdantic.examples.pydantic import Quest diagram1 = erd.create(Party, terminal_models=[Quest]) diagram1 ``` -------------------------------- ### Python API: erdantic.draw Source: https://context7.com/drivendataorg/erdantic/llms.txt Use erdantic.draw for a one-shot function to create and render a diagram to a file. Supports multiple root models, terminal models, custom Graphviz attributes, and module searching. ```python import erdantic from erdantic.examples.pydantic import Party erdantic.draw(Party, out="diagram.png") ``` ```python from erdantic.examples.pydantic import Quest, Party erdantic.draw(Party, Quest, out="diagram.svg") ``` ```python from erdantic.examples.pydantic import Party, QuestGiver erdantic.draw(Party, out="party_limited.png", terminal_models=[QuestGiver]) ``` ```python erdantic.draw( Party, out="diagram.png", graph_attr={"nodesep": "1.0", "ranksep": "2.0"}, node_attr={"fontsize": "12"}, edge_attr={"color": "blue"}, ) ``` ```python import erdantic.examples.pydantic as pydantic_examples erdantic.draw(pydantic_examples, out="all_pydantic.png") ``` -------------------------------- ### Access Diagram Models Source: https://github.com/drivendataorg/erdantic/blob/main/docs/notebooks/examples/msgspec.ipynb Retrieves a list of model keys from the diagram object, which contains ModelInfo objects for each model. ```python list(diagram.models.keys()) ``` -------------------------------- ### Python Library: Specify Terminal Models Source: https://github.com/drivendataorg/erdantic/blob/main/docs/notebooks/examples/dataclasses.ipynb When using the Python library, pass a list of terminal models to the `terminal_models` keyword argument of the `erd.create` function. This is equivalent to using the -t option in the CLI. ```python from erdantic.examples.dataclasses import Quest diagram1 = erd.create(Party, terminal_models=[Quest]) diagram1 ``` ```python diagram2 = erd.create(Quest) diagram2 ``` -------------------------------- ### Register a Custom Plugin Source: https://github.com/drivendataorg/erdantic/blob/main/docs/docs/extending.md Registers a custom plugin with erdantic using a key identifier and the predicate and field extractor functions. Overwrites existing plugins if the key already exists. ```python register_plugin(key="my_plugin", predicate=my_predicate, field_extractor=my_field_extractor) ``` -------------------------------- ### Python API: erdantic.to_dot Source: https://context7.com/drivendataorg/erdantic/llms.txt Generates the Graphviz DOT language string for the diagram without rendering an image. Useful for programmatic manipulation or integration with other tools. ```APIDOC ## Python API: erdantic.to_dot Generates the Graphviz DOT language string for the diagram without rendering an image. ### Usage ```python import erdantic from erdantic.examples.pydantic import Party dot_string = erdantic.to_dot(Party) print(dot_string[:300]) # digraph "Entity Relationship Diagram created by erdantic" { ``` ``` -------------------------------- ### Define Adventurer Class with attrs Source: https://github.com/drivendataorg/erdantic/blob/main/docs/notebooks/examples/attrs.ipynb Defines an Adventurer class using attrs' @define decorator. This class includes various attributes with type hints, suitable for data modeling. ```python from enum import Enum class Alignment(Enum): LAWFUL_GOOD = 1 NEUTRAL_GOOD = 2 CHAOTIC_GOOD = 3 LAWFUL_NEUTRAL = 4 NEUTRAL = 5 CHAOTIC_NEUTRAL = 6 LAWFUL_EVIL = 7 NEUTRAL_EVIL = 8 CHAOTIC_EVIL = 9 @define class Adventurer: """A person often late for dinner but with a tale or two to tell. Attributes: name (str): Name of this adventurer profession (str): Profession of this adventurer level (int): Level of this adventurer alignment (Alignment): Alignment of this adventurer """ name: str profession: str level: int alignment: Alignment ``` -------------------------------- ### Define Party Model with Pydantic Source: https://github.com/drivendataorg/erdantic/blob/main/docs/notebooks/examples/pydantic.ipynb Defines a Pydantic model for a party, including a list of adventurers and a timestamp. This demonstrates the use of complex types like List and datetime. ```python class Party(BaseModel): """A group of adventurers finding themselves doing and saying things altogether unexpected. Attributes: name (str): Name that party is known by formed_datetime (datetime): Timestamp of when the party was formed members (List[Adventurer]): Adventurers that belong to this party """ name: str formed_datetime: datetime members: List[Adventurer] ``` -------------------------------- ### Find Models in a Module with Erdantic Source: https://context7.com/drivendataorg/erdantic/llms.txt Use `find_models` to iterate over all data model classes within a given module. You can optionally restrict the search to models associated with a specific plugin. ```python from erdantic.convenience import find_models import erdantic.examples.pydantic as pydantic_examples import erdantic.examples.attrs as attrs_examples # Find all models in a module for cls in find_models(pydantic_examples): print(cls) # # # # # Restrict to a specific plugin for cls in find_models(pydantic_examples, limit_search_models_to=["pydantic"]): print(cls.__name__) # Adventurer, Party, Quest, QuestGiver # Useful for building diagrams selectively import erdantic diagram = erdantic.create( *find_models(pydantic_examples, limit_search_models_to=["pydantic"]) ) diagram.draw("pydantic_models.png") ``` -------------------------------- ### Define Pydantic Quest Model Source: https://github.com/drivendataorg/erdantic/blob/main/docs/notebooks/examples/pydantic.ipynb Defines a Pydantic model for a Quest, including fields for name, faction, and location. The 'faction' field is optional. ```python class Quest(BaseModel): """A task to complete, with some monetary reward. Attributes: name (str): Name of this quest faction (Optional[str]): Faction this quest belongs to location (str): Location this quest can be found """ name: str faction: Optional[str] = None location: str ``` -------------------------------- ### Define a Dataclass Source: https://github.com/drivendataorg/erdantic/blob/main/docs/notebooks/examples/dataclasses.ipynb Use the @dataclass decorator to automatically generate methods like __init__, __repr__, etc. for a class. This is useful for creating simple data-holding classes. ```python from dataclasses import dataclass @dataclass class Adventurer: """A person often late for dinner but with a tale or two to tell. Attributes: name (str): Name of this adventurer profession (str): Profession of this adventurer level (int): Level of this adventurer alignment (Alignment): Alignment of this adventurer """ name: str profession: str level: int alignment: Alignment ``` -------------------------------- ### Inspecting and Modifying Diagram Edges Source: https://context7.com/drivendataorg/erdantic/llms.txt Shows how to inspect edges in an EntityRelationshipDiagram, including source/target model names, field names, cardinality, and modality. It also demonstrates overriding edge properties and adding source-side annotations. ```python from erdantic.core import ( EntityRelationshipDiagram, Edge, Cardinality, Modality, FullyQualifiedName ) from erdantic.examples.pydantic import Party, Quest diagram = EntityRelationshipDiagram() diagram.add_model(Party) # Inspect edges for key, edge in diagram.edges.items(): print( f" {edge.source_model_full_name}.{edge.source_field_name} " f"--[{edge.target_cardinality.value},{edge.target_modality.value}]--> " f"{edge.target_model_full_name}" ) # erdantic.examples.pydantic.Party.active_quest --[one,zero]--> erdantic.examples.pydantic.Quest # erdantic.examples.pydantic.Party.members --[many,unspecified]--> erdantic.examples.pydantic.Adventurer # erdantic.examples.pydantic.Quest.giver --[one,one]--> erdantic.examples.pydantic.QuestGiver # Override modality for a specific edge party_members_edge_key = next( k for k, e in diagram.edges.items() if e.source_field_name == "members" ) diagram.edges[party_members_edge_key].target_modality = Modality.ONE # Add source-side cardinality annotation (not set by default) diagram.edges[party_members_edge_key].source_cardinality = Cardinality.ONE diagram.edges[party_members_edge_key].source_modality = Modality.ONE diagram.draw("annotated.png") ``` -------------------------------- ### List All Edges in Dataclass Diagram Source: https://github.com/drivendataorg/erdantic/blob/main/docs/notebooks/examples/dataclasses.ipynb This code snippet shows how to retrieve a list of all edges present in a diagram generated from Python dataclasses. It's useful for inspecting the relationships between models. ```python diagram.edges[ "erdantic.examples.dataclasses.Party-members-erdantic.examples.dataclasses.Adventurer" ] ``` -------------------------------- ### Python API: erdantic.to_dot Source: https://context7.com/drivendataorg/erdantic/llms.txt Use erdantic.to_dot to generate the Graphviz DOT language string for a diagram without rendering an image. This is useful for programmatic access to the DOT output. ```python import erdantic from erdantic.examples.pydantic import Party dot_string = erdantic.to_dot(Party) print(dot_string[:300]) # digraph "Entity Relationship Diagram created by erdantic" { ```