erdantic.base¶
Attributes¶
model_adapter_registry: Dict[str, Type[erdantic.base.Model]]
¶
    Registry of concrete Model adapter subclasses. A concrete Model
subclass must be registered for it to be available to the diagram creation workflow.
Classes¶
        
Field            (ABC, Generic)
        
¶
    Abstract base class that adapts a field object of a data model class to work with erdantic. Concrete implementations should subclass and implement abstract methods.
Attributes:
| Name | Type | Description | 
|---|---|---|
field | 
        FT | 
        Field object on a data model class associated with this adapter  | 
      
Source code in erdantic/base.py
          class Field(ABC, Generic[FT]):
    """Abstract base class that adapts a field object of a data model class to work with erdantic.
    Concrete implementations should subclass and implement abstract methods.
    Attributes:
        field (FT): Field object on a data model class associated with this adapter
    """
    @abstractmethod
    def __init__(self, field: FT):
        """Initialize Field adapter instance.
        Args:
            field: Field object to associate with this adapter instance
        """
        self.field: Final[FT] = field
    @property
    @abstractmethod
    def name(self) -> str:  # pragma: no cover
        """Name of this field on the parent data model."""
    @property
    @abstractmethod
    def type_obj(self) -> Union[type, GenericAlias]:
        """Python type object for this field."""
        pass
    @abstractmethod
    def is_many(self) -> bool:  # pragma: no cover
        """Check whether this field represents a one-to-one or one-to-many relationship.
        Returns:
            bool: True if one-to-many relationship, else False.
        """
        pass
    @abstractmethod
    def is_nullable(self) -> bool:  # pragma: no cover
        """Check whether this field is nullable, i.e., can be `None`.
        Returns:
            bool: True if nullable, else False.
        """
        pass
    @property
    def type_name(self) -> str:  # pragma: no cover
        """String representation of the Python type annotation for this field."""
        return repr_type(self.type_obj)
    def dot_row(self) -> str:
        """Returns the DOT language "HTML-like" syntax specification of a row detailing this field
        that is part of a table describing the field's parent data model. It is used as part the
        `label` attribute of data model's node in the graph's DOT representation.
        Returns:
            str: DOT language for table row
        """
        return _row_template.format(name=self.name, type_name=self.type_name)
    def __eq__(self, other: Any) -> bool:
        return isinstance(other, type(self)) and hash(self) == hash(other)
    def __hash__(self) -> int:
        return id(self.field)
    def __repr__(self) -> str:
        return f"<{type(self).__name__}: '{self.name}', {self.type_name}>"
Attributes¶
name: str
  
      property
      readonly
  
¶
    Name of this field on the parent data model.
type_name: str
  
      property
      readonly
  
¶
    String representation of the Python type annotation for this field.
type_obj: Union[type, _GenericAlias]
  
      property
      readonly
  
¶
    Python type object for this field.
Methods¶
__init__(self, field: +FT)
  
      special
  
¶
    Initialize Field adapter instance.
Parameters:
| Name | Type | Description | Default | 
|---|---|---|---|
field | 
        +FT | 
        Field object to associate with this adapter instance  | 
        required | 
Source code in erdantic/base.py
          @abstractmethod
def __init__(self, field: FT):
    """Initialize Field adapter instance.
    Args:
        field: Field object to associate with this adapter instance
    """
    self.field: Final[FT] = field
dot_row(self) -> str
¶
    Returns the DOT language "HTML-like" syntax specification of a row detailing this field
that is part of a table describing the field's parent data model. It is used as part the
label attribute of data model's node in the graph's DOT representation.
Returns:
| Type | Description | 
|---|---|
str | 
      DOT language for table row  | 
    
Source code in erdantic/base.py
          def dot_row(self) -> str:
    """Returns the DOT language "HTML-like" syntax specification of a row detailing this field
    that is part of a table describing the field's parent data model. It is used as part the
    `label` attribute of data model's node in the graph's DOT representation.
    Returns:
        str: DOT language for table row
    """
    return _row_template.format(name=self.name, type_name=self.type_name)
is_many(self) -> bool
¶
    Check whether this field represents a one-to-one or one-to-many relationship.
Returns:
| Type | Description | 
|---|---|
bool | 
      True if one-to-many relationship, else False.  | 
    
Source code in erdantic/base.py
          @abstractmethod
def is_many(self) -> bool:  # pragma: no cover
    """Check whether this field represents a one-to-one or one-to-many relationship.
    Returns:
        bool: True if one-to-many relationship, else False.
    """
    pass
is_nullable(self) -> bool
¶
    Check whether this field is nullable, i.e., can be None.
Returns:
| Type | Description | 
|---|---|
bool | 
      True if nullable, else False.  | 
    
Source code in erdantic/base.py
          @abstractmethod
def is_nullable(self) -> bool:  # pragma: no cover
    """Check whether this field is nullable, i.e., can be `None`.
    Returns:
        bool: True if nullable, else False.
    """
    pass
        
Model            (ABC, Generic)
        
¶
    Abstract base class that adapts a data model class to work with erdantic. Instances represent a node in our entity relationship diagram graph. Concrete implementations should subclass and implement abstract methods.
Attributes:
| Name | Type | Description | 
|---|---|---|
model | 
        MT | 
        Data model class associated with this adapter  | 
      
forward_ref_help | 
        Optional[str] | 
        Instructions for how to resolve an unevaluated forward reference in a field's type declaration.  | 
      
Source code in erdantic/base.py
          class Model(ABC, Generic[MT]):
    """Abstract base class that adapts a data model class to work with erdantic. Instances
    represent a node in our entity relationship diagram graph. Concrete implementations should
    subclass and implement abstract methods.
    Attributes:
        model (MT): Data model class associated with this adapter
        forward_ref_help (Optional[str]): Instructions for how to resolve an unevaluated forward
            reference in a field's type declaration.
    """
    forward_ref_help: Optional[str] = None
    @abstractmethod
    def __init__(self, model: MT):
        """Initialize model adapter instance.
        Args:
            model: Data model class to associate with this adapter instance
        """
        self.model: Final[MT] = model
    @property
    @abstractmethod
    def fields(self) -> List[Field]:  # pragma: no cover
        """List of fields defined on this data model."""
        pass
    @staticmethod
    @abstractmethod
    def is_model_type(obj: Any) -> bool:  # pragma: no cover
        """Check if object is the type of data model class that this model adapter works with."""
        pass
    @property
    def name(self) -> str:  # pragma: no cover
        """Name of this data model."""
        return self.model.__name__
    @property
    def docstring(self) -> str:
        """Docstring for this data model."""
        out = f"{self.model.__module__}.{self.model.__qualname__}"
        docstring = inspect.getdoc(self.model)
        if docstring:
            out += "\n\n" + docstring + "\n"
        return out
    @property
    def key(self) -> str:
        """Human-readable unique identifier for this data model. Should be stable across
        sessions."""
        return f"{self.model.__module__}.{self.model.__qualname__}"
    def dot_label(self) -> str:
        """Returns the DOT language "HTML-like" syntax specification of a table for this data
        model. It is used as the `label` attribute of data model's node in the graph's DOT
        representation.
        Returns:
            str: DOT language for table
        """
        rows = "\n".join(field.dot_row() for field in self.fields)
        return _table_template.format(name=self.name, rows=rows).replace("\n", "")
    def __eq__(self, other) -> bool:
        return isinstance(other, type(self)) and hash(self) == hash(other)
    def __hash__(self) -> int:
        return hash(self.key)
    def __lt__(self, other) -> bool:
        if isinstance(other, Model):
            return self.key < other.key
        return NotImplemented
    def __repr__(self) -> str:
        return f"{type(self).__name__}({self.name})"
Attributes¶
docstring: str
  
      property
      readonly
  
¶
    Docstring for this data model.
fields: List[erdantic.base.Field]
  
      property
      readonly
  
¶
    List of fields defined on this data model.
forward_ref_help: Optional[str]
¶
    
key: str
  
      property
      readonly
  
¶
    Human-readable unique identifier for this data model. Should be stable across sessions.
name: str
  
      property
      readonly
  
¶
    Name of this data model.
Methods¶
__init__(self, model: +MT)
  
      special
  
¶
    Initialize model adapter instance.
Parameters:
| Name | Type | Description | Default | 
|---|---|---|---|
model | 
        +MT | 
        Data model class to associate with this adapter instance  | 
        required | 
Source code in erdantic/base.py
          @abstractmethod
def __init__(self, model: MT):
    """Initialize model adapter instance.
    Args:
        model: Data model class to associate with this adapter instance
    """
    self.model: Final[MT] = model
dot_label(self) -> str
¶
    Returns the DOT language "HTML-like" syntax specification of a table for this data
model. It is used as the label attribute of data model's node in the graph's DOT
representation.
Returns:
| Type | Description | 
|---|---|
str | 
      DOT language for table  | 
    
Source code in erdantic/base.py
          def dot_label(self) -> str:
    """Returns the DOT language "HTML-like" syntax specification of a table for this data
    model. It is used as the `label` attribute of data model's node in the graph's DOT
    representation.
    Returns:
        str: DOT language for table
    """
    rows = "\n".join(field.dot_row() for field in self.fields)
    return _table_template.format(name=self.name, rows=rows).replace("\n", "")
is_model_type(obj: Any) -> bool
  
      staticmethod
  
¶
    Check if object is the type of data model class that this model adapter works with.
Source code in erdantic/base.py
          @staticmethod
@abstractmethod
def is_model_type(obj: Any) -> bool:  # pragma: no cover
    """Check if object is the type of data model class that this model adapter works with."""
    pass
Functions¶
register_model_adapter(type_name: str) -> Callable[[Type[erdantic.base.Model]], Type[erdantic.base.Model]]
¶
    Create decorator to register a concrete Model adapter subclass
that will be identified under the key type_name. A concrete Model subclass must be
registered for it to be available to the diagram creation workflow.
Parameters:
| Name | Type | Description | Default | 
|---|---|---|---|
type_name | 
        str | 
        Key used to identify concrete   | 
        required | 
Returns:
| Type | Description | 
|---|---|
Callable[[Type[Model]], Type[Model]] | 
      A registration decorator for a concrete   | 
    
Source code in erdantic/base.py
          def register_model_adapter(type_name: str) -> Callable[[Type[Model]], Type[Model]]:
    """Create decorator to register a concrete [`Model`][erdantic.base.Model] adapter subclass
    that will be identified under the key `type_name`. A concrete `Model` subclass must be
    registered for it to be available to the diagram creation workflow.
    Args:
        type_name (str): Key used to identify concrete `Model` adapter subclass
    Returns:
        Callable[[Type[Model]], Type[Model]]: A registration decorator for a concrete `Model`
            adapter subclass
    """
    def decorator(cls: type) -> type:
        global model_adapter_registry
        if not issubclass(cls, Model):
            raise InvalidModelAdapterError(
                "Only subclasses of erdantic.base.Model can be "
                "registered as erdantic model adapters."
            )
        model_adapter_registry[type_name] = cls
        return cls
    return decorator