Skip to content

type_bridge.attribute

attribute

TypeDB attribute types - base classes and concrete implementations.

This package provides the attribute type system for TypeBridge, including: - Base Attribute ABC - Concrete attribute types (String, Integer, Double, Boolean, Date, DateTime, DateTimeTZ, Decimal, Duration) - Flag system for annotations (Key, Unique, Card)

Attribute

Attribute(value=None)

Bases: ABC

Base class for TypeDB attributes.

Attributes in TypeDB are value types that can be owned by entities and relations.

Attribute instances can store values, allowing type-safe construction: Name("Alice") # Creates Name instance with value "Alice" Age(30) # Creates Age instance with value 30

Type name formatting

You can control how the class name is converted to TypeDB attribute name using the 'case' class variable or 'attr_name' for explicit control.

Example

class Name(String): pass # TypeDB attribute: "Name" (default CLASS_NAME)

class PersonName(String): case = TypeNameCase.SNAKE_CASE # TypeDB attribute: "person_name"

class PersonName(String): attr_name = "full_name" # Explicit override

class Age(Integer): pass

class Person(Entity): name: Name age: Age

Direct instantiation with wrapped types (best practice):

person = Person(name=Name("Alice"), age=Age(30))

Initialize attribute with a value.

Parameters:

Name Type Description Default
value Any

The value to store in this attribute instance

None
Source code in type_bridge/attribute/base.py
@abstractmethod
def __init__(self, value: Any = None):
    """Initialize attribute with a value.

    Args:
        value: The value to store in this attribute instance
    """
    self._value = value

value property

value

Get the stored value.

__init_subclass__

__init_subclass__(**kwargs)

Called when a subclass is created.

Source code in type_bridge/attribute/base.py
def __init_subclass__(cls, **kwargs):
    """Called when a subclass is created."""
    super().__init_subclass__(**kwargs)

    # Import here to avoid circular dependency
    from type_bridge.attribute.flags import (
        AttributeFlags,
        TypeNameCase,
        format_type_name,
    )

    # Determine the attribute name for this subclass
    # Priority: flags.name > attr_name > flags.case > class.case > default CLASS_NAME
    flags = getattr(cls, "flags", None)
    if isinstance(flags, AttributeFlags) and flags.name is not None:
        # flags.name has highest priority
        computed_name = flags.name
    elif cls.attr_name is not None:
        # Explicit attr_name takes precedence over formatting
        computed_name = cls.attr_name
    else:
        # Determine case formatting
        # Priority: flags.case > class.case > default CLASS_NAME
        if isinstance(flags, AttributeFlags) and flags.case is not None:
            case = flags.case
        elif cls.case is not None:
            case = cls.case
        else:
            case = TypeNameCase.CLASS_NAME

        # Apply case formatting to class name
        computed_name = format_type_name(cls.__name__, case)

    # Always set the attribute name for each new subclass (don't inherit from parent)
    # This ensures Name(String) gets _attr_name="name", not "string"
    cls._attr_name = computed_name

    # Skip validation for built-in attribute types (Boolean, Integer, String, etc.)
    # These are framework-provided and intentionally use TypeQL reserved words
    is_builtin = cls.__module__.startswith("type_bridge.attribute")

    # Validate attribute name doesn't conflict with TypeDB built-ins
    # Only validate user-defined attribute types, not framework built-ins
    if not is_builtin:
        _validate_attribute_name(cls._attr_name, cls.__name__)

__str__

__str__()

String representation returns the stored value.

Source code in type_bridge/attribute/base.py
def __str__(self) -> str:
    """String representation returns the stored value."""
    return str(self._value) if self._value is not None else ""

__repr__

__repr__()

Repr shows the attribute type and value.

Source code in type_bridge/attribute/base.py
def __repr__(self) -> str:
    """Repr shows the attribute type and value."""
    cls_name = self.__class__.__name__
    return f"{cls_name}({self._value!r})"

__eq__

__eq__(other)

Compare attribute with another attribute instance.

For strict type safety, Attribute instances do NOT compare equal to raw values. To access the raw value, use the .value property.

Examples:

Age(20) == Age(20) # True (same type, same value) Age(20) == Id(20) # False (different types!) Age(20) == 20 # False (not equal to raw value!) Age(20).value == 20 # True (access raw value explicitly)

Source code in type_bridge/attribute/base.py
def __eq__(self, other: object) -> bool:
    """Compare attribute with another attribute instance.

    For strict type safety, Attribute instances do NOT compare equal to raw values.
    To access the raw value, use the `.value` property.

    Examples:
        Age(20) == Age(20)  # True (same type, same value)
        Age(20) == Id(20)   # False (different types!)
        Age(20) == 20       # False (not equal to raw value!)
        Age(20).value == 20 # True (access raw value explicitly)
    """
    if isinstance(other, Attribute):
        # Compare two attribute instances: both type and value must match
        return type(self) is type(other) and self._value == other._value
    # Do not compare with non-Attribute objects (strict type safety)
    return False

__hash__

__hash__()

Make attribute hashable based on its type and value.

Source code in type_bridge/attribute/base.py
def __hash__(self) -> int:
    """Make attribute hashable based on its type and value."""
    return hash((type(self), self._value))

get_attribute_name classmethod

get_attribute_name()

Get the TypeDB attribute name.

If attr_name is explicitly set, it is used as-is. Otherwise, the class name is formatted according to the case parameter. Default case is CLASS_NAME (preserves class name as-is).

Source code in type_bridge/attribute/base.py
@classmethod
def get_attribute_name(cls) -> str:
    """Get the TypeDB attribute name.

    If attr_name is explicitly set, it is used as-is.
    Otherwise, the class name is formatted according to the case parameter.
    Default case is CLASS_NAME (preserves class name as-is).
    """
    return cls._attr_name or cls.__name__

get_value_type classmethod

get_value_type()

Get the TypeDB value type.

Source code in type_bridge/attribute/base.py
@classmethod
def get_value_type(cls) -> str:
    """Get the TypeDB value type."""
    return cls.value_type

is_key classmethod

is_key()

Check if this attribute is a key.

Source code in type_bridge/attribute/base.py
@classmethod
def is_key(cls) -> bool:
    """Check if this attribute is a key."""
    return cls._is_key

is_abstract classmethod

is_abstract()

Check if this attribute is abstract.

Source code in type_bridge/attribute/base.py
@classmethod
def is_abstract(cls) -> bool:
    """Check if this attribute is abstract."""
    return cls.abstract

is_independent classmethod

is_independent()

Check if this attribute is independent (can exist without owners).

Source code in type_bridge/attribute/base.py
@classmethod
def is_independent(cls) -> bool:
    """Check if this attribute is independent (can exist without owners)."""
    return cls.independent

get_owners classmethod

get_owners()

Get all Entity/Relation classes that own this attribute.

Returns:

Type Description
set[type[TypeDBType]]

Set of model classes that define this attribute as a field.

set[type[TypeDBType]]

Does not require a database connection (static discovery).

Source code in type_bridge/attribute/base.py
@classmethod
def get_owners(cls) -> "set[type[TypeDBType]]":
    """Get all Entity/Relation classes that own this attribute.

    Returns:
        Set of model classes that define this attribute as a field.
        Does not require a database connection (static discovery).
    """
    from type_bridge.models.registry import ModelRegistry

    return ModelRegistry.get_attribute_owners(cls)

get_supertype classmethod

get_supertype()

Get the supertype if this attribute extends another.

Source code in type_bridge/attribute/base.py
@classmethod
def get_supertype(cls) -> str | None:
    """Get the supertype if this attribute extends another."""
    return cls._supertype

to_schema_definition classmethod

to_schema_definition()

Generate TypeQL schema definition for this attribute.

Includes support for TypeDB annotations: - @abstract (comes right after attribute name) - @independent (comes right after attribute name, allows standalone existence) - @range(min..max) from range_constraint ClassVar (after value type) - @regex("pattern") from regex ClassVar (after value type) - @values("a", "b", ...) from allowed_values ClassVar (after value type)

Returns:

Type Description
str

TypeQL schema definition string

Source code in type_bridge/attribute/base.py
@classmethod
def to_schema_definition(cls) -> str:
    """Generate TypeQL schema definition for this attribute.

    Includes support for TypeDB annotations:
    - @abstract (comes right after attribute name)
    - @independent (comes right after attribute name, allows standalone existence)
    - @range(min..max) from range_constraint ClassVar (after value type)
    - @regex("pattern") from regex ClassVar (after value type)
    - @values("a", "b", ...) from allowed_values ClassVar (after value type)

    Returns:
        TypeQL schema definition string
    """
    from type_bridge.typeql.annotations import format_type_annotations

    attr_name = cls.get_attribute_name()
    value_type = cls.get_value_type()

    # Build type-level annotations (@abstract, @independent come right after name)
    type_annotations = format_type_annotations(
        abstract=cls.abstract,
        independent=cls.independent,
    )

    # Build definition: attribute name [@abstract] [@independent], [sub parent,] value type;
    if type_annotations:
        annotations_str = " ".join(type_annotations)
        if cls._supertype:
            definition = f"attribute {attr_name} {annotations_str}, sub {cls._supertype}, value {value_type}"
        else:
            definition = f"attribute {attr_name} {annotations_str}, value {value_type}"
    elif cls._supertype:
        definition = f"attribute {attr_name} sub {cls._supertype}, value {value_type}"
    else:
        definition = f"attribute {attr_name}, value {value_type}"

    # Add @range annotation if range_constraint is defined (after value type)
    range_constraint = getattr(cls, "range_constraint", None)
    if range_constraint is not None:
        range_min, range_max = range_constraint
        # Format as @range(min..max), @range(min..), or @range(..max)
        min_part = range_min if range_min is not None else ""
        max_part = range_max if range_max is not None else ""
        definition += f" @range({min_part}..{max_part})"

    # Add @regex annotation if regex_pattern is defined (after value type)
    # Note: Use regex_pattern (not regex) to avoid conflict with String.regex() query method
    regex_pattern = getattr(cls, "regex_pattern", None)
    if regex_pattern is not None and isinstance(regex_pattern, str):
        # Escape any quotes in the pattern
        escaped_pattern = regex_pattern.replace('"', '\\"')
        definition += f' @regex("{escaped_pattern}")'

    # Add @values annotation if allowed_values is defined (after value type)
    allowed_values = getattr(cls, "allowed_values", None)
    if allowed_values is not None and isinstance(allowed_values, tuple):
        # Format as @values("a", "b", ...)
        values_str = ", ".join(f'"{v}"' for v in allowed_values)
        definition += f" @values({values_str})"

    return definition + ";"

gt classmethod

gt(value)

Create greater-than comparison expression.

Parameters:

Name Type Description Default
value Attribute

Value to compare against

required

Returns:

Type Description
ComparisonExpr

ComparisonExpr for attr > value

Example

Age.gt(Age(30)) # age > 30

Source code in type_bridge/attribute/base.py
@classmethod
def gt(cls, value: "Attribute") -> "ComparisonExpr":
    """Create greater-than comparison expression.

    Args:
        value: Value to compare against

    Returns:
        ComparisonExpr for attr > value

    Example:
        Age.gt(Age(30))  # age > 30
    """
    from type_bridge.expressions import ComparisonExpr

    return ComparisonExpr(attr_type=cls, operator=">", value=value)

lt classmethod

lt(value)

Create less-than comparison expression.

Parameters:

Name Type Description Default
value Attribute

Value to compare against

required

Returns:

Type Description
ComparisonExpr

ComparisonExpr for attr < value

Example

Age.lt(Age(30)) # age < 30

Source code in type_bridge/attribute/base.py
@classmethod
def lt(cls, value: "Attribute") -> "ComparisonExpr":
    """Create less-than comparison expression.

    Args:
        value: Value to compare against

    Returns:
        ComparisonExpr for attr < value

    Example:
        Age.lt(Age(30))  # age < 30
    """
    from type_bridge.expressions import ComparisonExpr

    return ComparisonExpr(attr_type=cls, operator="<", value=value)

gte classmethod

gte(value)

Create greater-than-or-equal comparison expression.

Parameters:

Name Type Description Default
value Attribute

Value to compare against

required

Returns:

Type Description
ComparisonExpr

ComparisonExpr for attr >= value

Example

Salary.gte(Salary(80000.0)) # salary >= 80000

Source code in type_bridge/attribute/base.py
@classmethod
def gte(cls, value: "Attribute") -> "ComparisonExpr":
    """Create greater-than-or-equal comparison expression.

    Args:
        value: Value to compare against

    Returns:
        ComparisonExpr for attr >= value

    Example:
        Salary.gte(Salary(80000.0))  # salary >= 80000
    """
    from type_bridge.expressions import ComparisonExpr

    return ComparisonExpr(attr_type=cls, operator=">=", value=value)

lte classmethod

lte(value)

Create less-than-or-equal comparison expression.

Parameters:

Name Type Description Default
value Attribute

Value to compare against

required

Returns:

Type Description
ComparisonExpr

ComparisonExpr for attr <= value

Example

Age.lte(Age(65)) # age <= 65

Source code in type_bridge/attribute/base.py
@classmethod
def lte(cls, value: "Attribute") -> "ComparisonExpr":
    """Create less-than-or-equal comparison expression.

    Args:
        value: Value to compare against

    Returns:
        ComparisonExpr for attr <= value

    Example:
        Age.lte(Age(65))  # age <= 65
    """
    from type_bridge.expressions import ComparisonExpr

    return ComparisonExpr(attr_type=cls, operator="<=", value=value)

eq classmethod

eq(value)

Create equality comparison expression.

Parameters:

Name Type Description Default
value Attribute

Value to compare against

required

Returns:

Type Description
ComparisonExpr

ComparisonExpr for attr == value

Example

Status.eq(Status("active")) # status == "active"

Source code in type_bridge/attribute/base.py
@classmethod
def eq(cls, value: "Attribute") -> "ComparisonExpr":
    """Create equality comparison expression.

    Args:
        value: Value to compare against

    Returns:
        ComparisonExpr for attr == value

    Example:
        Status.eq(Status("active"))  # status == "active"
    """
    from type_bridge.expressions import ComparisonExpr

    return ComparisonExpr(attr_type=cls, operator="==", value=value)

neq classmethod

neq(value)

Create not-equal comparison expression.

Parameters:

Name Type Description Default
value Attribute

Value to compare against

required

Returns:

Type Description
ComparisonExpr

ComparisonExpr for attr != value

Example

Status.neq(Status("deleted")) # status != "deleted"

Source code in type_bridge/attribute/base.py
@classmethod
def neq(cls, value: "Attribute") -> "ComparisonExpr":
    """Create not-equal comparison expression.

    Args:
        value: Value to compare against

    Returns:
        ComparisonExpr for attr != value

    Example:
        Status.neq(Status("deleted"))  # status != "deleted"
    """
    from type_bridge.expressions import ComparisonExpr

    return ComparisonExpr(attr_type=cls, operator="!=", value=value)

sum classmethod

sum()

Create sum aggregation expression.

Returns:

Type Description
AggregateExpr

AggregateExpr for sum(attr)

Example

Salary.sum() # sum of all salaries

Source code in type_bridge/attribute/base.py
@classmethod
def sum(cls) -> "AggregateExpr":
    """Create sum aggregation expression.

    Returns:
        AggregateExpr for sum(attr)

    Example:
        Salary.sum()  # sum of all salaries
    """
    from type_bridge.expressions import AggregateExpr

    return AggregateExpr(attr_type=cls, function="sum")

avg classmethod

avg()

Create average (mean) aggregation expression.

Note

Automatically converts to TypeQL 'mean' function. TypeDB 3.x uses 'mean' instead of 'avg'.

Returns:

Type Description
AggregateExpr

AggregateExpr for mean(attr)

Example

Age.avg() # Generates TypeQL: mean($age)

Source code in type_bridge/attribute/base.py
@classmethod
def avg(cls) -> "AggregateExpr":
    """Create average (mean) aggregation expression.

    Note:
        Automatically converts to TypeQL 'mean' function.
        TypeDB 3.x uses 'mean' instead of 'avg'.

    Returns:
        AggregateExpr for mean(attr)

    Example:
        Age.avg()  # Generates TypeQL: mean($age)
    """
    from type_bridge.expressions import AggregateExpr

    return AggregateExpr(attr_type=cls, function="mean")

max classmethod

max()

Create maximum aggregation expression.

Returns:

Type Description
AggregateExpr

AggregateExpr for max(attr)

Example

Score.max() # maximum score

Source code in type_bridge/attribute/base.py
@classmethod
def max(cls) -> "AggregateExpr":
    """Create maximum aggregation expression.

    Returns:
        AggregateExpr for max(attr)

    Example:
        Score.max()  # maximum score
    """
    from type_bridge.expressions import AggregateExpr

    return AggregateExpr(attr_type=cls, function="max")

min classmethod

min()

Create minimum aggregation expression.

Returns:

Type Description
AggregateExpr

AggregateExpr for min(attr)

Example

Price.min() # minimum price

Source code in type_bridge/attribute/base.py
@classmethod
def min(cls) -> "AggregateExpr":
    """Create minimum aggregation expression.

    Returns:
        AggregateExpr for min(attr)

    Example:
        Price.min()  # minimum price
    """
    from type_bridge.expressions import AggregateExpr

    return AggregateExpr(attr_type=cls, function="min")

median classmethod

median()

Create median aggregation expression.

Returns:

Type Description
AggregateExpr

AggregateExpr for median(attr)

Example

Salary.median() # median salary

Source code in type_bridge/attribute/base.py
@classmethod
def median(cls) -> "AggregateExpr":
    """Create median aggregation expression.

    Returns:
        AggregateExpr for median(attr)

    Example:
        Salary.median()  # median salary
    """
    from type_bridge.expressions import AggregateExpr

    return AggregateExpr(attr_type=cls, function="median")

std classmethod

std()

Create standard deviation aggregation expression.

Returns:

Type Description
AggregateExpr

AggregateExpr for std(attr)

Example

Score.std() # standard deviation of scores

Source code in type_bridge/attribute/base.py
@classmethod
def std(cls) -> "AggregateExpr":
    """Create standard deviation aggregation expression.

    Returns:
        AggregateExpr for std(attr)

    Example:
        Score.std()  # standard deviation of scores
    """
    from type_bridge.expressions import AggregateExpr

    return AggregateExpr(attr_type=cls, function="std")

__get_pydantic_core_schema__ classmethod

__get_pydantic_core_schema__(source_type, handler)

Unified Pydantic schema generation for all attribute types.

This base implementation handles the common patterns: - Serialization: extract _value from attribute instances - Validation: wrap raw values in attribute instances - Literal type support (for types that enable it)

Subclasses can override for completely custom behavior, or override the helper methods (_pydantic_serialize, _pydantic_validate, etc.) for targeted customization.

Source code in type_bridge/attribute/base.py
@classmethod
def __get_pydantic_core_schema__(
    cls, source_type: type[Any], handler: GetCoreSchemaHandler
) -> core_schema.CoreSchema:
    """Unified Pydantic schema generation for all attribute types.

    This base implementation handles the common patterns:
    - Serialization: extract _value from attribute instances
    - Validation: wrap raw values in attribute instances
    - Literal type support (for types that enable it)

    Subclasses can override for completely custom behavior, or override
    the helper methods (_pydantic_serialize, _pydantic_validate, etc.)
    for targeted customization.
    """
    # Check if this is a Literal type and the attribute supports it
    if cls._supports_literal_types() and get_origin(source_type) is Literal:
        # For Literal types, extract the raw value for constraint checking
        return core_schema.with_info_plain_validator_function(
            lambda v, _: v._value if isinstance(v, cls) else v,
            serialization=core_schema.plain_serializer_function_ser_schema(
                cls._pydantic_serialize,
                return_schema=cls._get_pydantic_return_schema(),
            ),
        )

    # Default: validate and wrap values in attribute instances
    return core_schema.with_info_plain_validator_function(
        lambda v, _: cls._pydantic_validate(v),
        serialization=core_schema.plain_serializer_function_ser_schema(
            cls._pydantic_serialize,
            return_schema=cls._get_pydantic_return_schema(),
        ),
    )

__class_getitem__ classmethod

__class_getitem__(item)

Allow generic subscription for type checking (e.g., Integer[int]).

Source code in type_bridge/attribute/base.py
@classmethod
def __class_getitem__(cls, item: object) -> type[Self]:
    """Allow generic subscription for type checking (e.g., Integer[int])."""
    return cls

build_lookup classmethod

build_lookup(lookup, value)

Build an expression for a lookup operator.

This method centralizes the logic for converting lookup names (e.g., 'gt', 'in') into TypeQL expressions. Subclasses (like String) should override this to handle type-specific lookups.

Parameters:

Name Type Description Default
lookup str

The lookup operator name (e.g., 'exact', 'gt', 'contains')

required
value Any

The value to filter by

required

Returns:

Type Description
Expression

Expression object representing the filter

Raises:

Type Description
ValueError

If the lookup operator is not supported by this attribute type

Source code in type_bridge/attribute/base.py
@classmethod
def build_lookup(cls, lookup: str, value: Any) -> "Expression":
    """Build an expression for a lookup operator.

    This method centralizes the logic for converting lookup names (e.g., 'gt', 'in')
    into TypeQL expressions. Subclasses (like String) should override this to
    handle type-specific lookups.

    Args:
        lookup: The lookup operator name (e.g., 'exact', 'gt', 'contains')
        value: The value to filter by

    Returns:
        Expression object representing the filter

    Raises:
        ValueError: If the lookup operator is not supported by this attribute type
    """
    from type_bridge.expressions import AttributeExistsExpr, BooleanExpr, Expression

    def _wrap(v: Any) -> Any:
        """Wrap raw value in attribute instance if needed."""
        if isinstance(v, cls):
            return v
        return cls(v)

    # Exact match
    if lookup in ("exact", "eq"):
        return cls.eq(_wrap(value))

    # Comparison operators
    if lookup in ("gt", "gte", "lt", "lte"):
        if not hasattr(cls, lookup):
            raise ValueError(f"Lookup '{lookup}' not supported for {cls.__name__}")
        return getattr(cls, lookup)(_wrap(value))

    # Membership test
    if lookup == "in":
        if not isinstance(value, (list, tuple, set)):
            raise ValueError(f"'{lookup}' lookup requires an iterable of values")
        values = list(value)
        if not values:
            raise ValueError(f"'{lookup}' lookup requires a non-empty iterable")

        eq_exprs: list[Expression] = [cls.eq(_wrap(v)) for v in values]
        if len(eq_exprs) == 1:
            return eq_exprs[0]
        return BooleanExpr("or", eq_exprs)

    # Null check
    if lookup == "isnull":
        if not isinstance(value, bool):
            raise ValueError(f"'{lookup}' lookup expects a boolean")
        return AttributeExistsExpr(cls, present=not value)

    raise ValueError(f"Unsupported lookup operator '{lookup}' for {cls.__name__}")

Boolean

Boolean(value)

Bases: Attribute

Boolean attribute type that accepts bool values.

Example

class IsActive(Boolean): pass

class IsVerified(Boolean): pass

Initialize Boolean attribute with a bool value.

Parameters:

Name Type Description Default
value bool

The boolean value to store

required
Source code in type_bridge/attribute/boolean.py
def __init__(self, value: bool):
    """Initialize Boolean attribute with a bool value.

    Args:
        value: The boolean value to store
    """
    super().__init__(value)

value property

value

Get the stored boolean value.

__bool__

__bool__()

Convert to bool.

Source code in type_bridge/attribute/boolean.py
def __bool__(self) -> bool:
    """Convert to bool."""
    return bool(self.value)

Date

Date(value)

Bases: Attribute

Date attribute type that accepts date values (date only, no time).

This maps to TypeDB's 'date' type, which is an ISO 8601 compliant date without time information.

Range: January 1, 262144 BCE to December 31, 262142 CE

Example

from datetime import date

class PublishDate(Date): pass

class BirthDate(Date): pass

Usage with date values

published = PublishDate(date(2024, 3, 30)) birthday = BirthDate(date(1990, 5, 15))

Initialize Date attribute with a date value.

Parameters:

Name Type Description Default
value date | str

The date value to store. Can be: - datetime.date instance - str in ISO 8601 format (YYYY-MM-DD)

required
Example

from datetime import date

From date instance

publish_date = PublishDate(date(2024, 3, 30))

From ISO string

publish_date = PublishDate("2024-03-30")

Source code in type_bridge/attribute/date.py
def __init__(self, value: date_type | str):
    """Initialize Date attribute with a date value.

    Args:
        value: The date value to store. Can be:
            - datetime.date instance
            - str in ISO 8601 format (YYYY-MM-DD)

    Example:
        from datetime import date

        # From date instance
        publish_date = PublishDate(date(2024, 3, 30))

        # From ISO string
        publish_date = PublishDate("2024-03-30")
    """
    if isinstance(value, str):
        value = date_type.fromisoformat(value)
    elif isinstance(value, datetime_type):
        # If passed a datetime, extract just the date part
        value = value.date()
    super().__init__(value)

value property

value

Get the stored date value.

__add__

__add__(other)

Add a Duration to this Date.

Parameters:

Name Type Description Default
other Any

A Duration to add to this date

required

Returns:

Type Description
Date

New Date with the duration added

Example

from type_bridge import Duration d = Date(date(2024, 1, 31)) duration = Duration("P1M") result = d + duration # Date(2024-02-29)

Source code in type_bridge/attribute/date.py
def __add__(self, other: Any) -> "Date":
    """Add a Duration to this Date.

    Args:
        other: A Duration to add to this date

    Returns:
        New Date with the duration added

    Example:
        from type_bridge import Duration
        d = Date(date(2024, 1, 31))
        duration = Duration("P1M")
        result = d + duration  # Date(2024-02-29)
    """
    from type_bridge.attribute.duration import Duration

    if isinstance(other, Duration):
        new_date = self.value + other.value
        # isodate returns datetime when adding Duration to date, extract .date()
        if isinstance(new_date, datetime_type):
            new_date = new_date.date()
        return Date(new_date)
    return NotImplemented

__radd__

__radd__(other)

Reverse addition for Duration + Date.

Source code in type_bridge/attribute/date.py
def __radd__(self, other: Any) -> "Date":
    """Reverse addition for Duration + Date."""
    return self.__add__(other)

__sub__

__sub__(other)

Subtract a Duration from this Date.

Parameters:

Name Type Description Default
other Any

A Duration to subtract from this date

required

Returns:

Type Description
Date

New Date with the duration subtracted

Example

from type_bridge import Duration d = Date(date(2024, 3, 31)) duration = Duration("P1M") result = d - duration # Date(2024-02-29)

Source code in type_bridge/attribute/date.py
def __sub__(self, other: Any) -> "Date":
    """Subtract a Duration from this Date.

    Args:
        other: A Duration to subtract from this date

    Returns:
        New Date with the duration subtracted

    Example:
        from type_bridge import Duration
        d = Date(date(2024, 3, 31))
        duration = Duration("P1M")
        result = d - duration  # Date(2024-02-29)
    """
    from type_bridge.attribute.duration import Duration

    if isinstance(other, Duration):
        new_date = self.value - other.value
        if isinstance(new_date, datetime_type):
            new_date = new_date.date()
        return Date(new_date)
    return NotImplemented

DateTime

DateTime(value)

Bases: Attribute

DateTime attribute type that accepts naive datetime values.

This maps to TypeDB's 'datetime' type, which does not include timezone information.

Example

class CreatedAt(DateTime): pass

Usage with naive datetime

event = Event(created_at=CreatedAt(datetime(2024, 1, 15, 10, 30, 45)))

Convert to DateTimeTZ

aware_dt = created_at.add_timezone() # Implicit: add system timezone aware_dt_utc = created_at.add_timezone(timezone.utc) # Explicit: add UTC

Initialize DateTime attribute with a datetime value.

Parameters:

Name Type Description Default
value datetime

The datetime value to store

required
Source code in type_bridge/attribute/datetime.py
def __init__(self, value: datetime_type):
    """Initialize DateTime attribute with a datetime value.

    Args:
        value: The datetime value to store
    """
    super().__init__(value)

value property

value

Get the stored datetime value.

add_timezone

add_timezone(tz=None)

Convert DateTime to DateTimeTZ by adding timezone information.

Implicit conversion (tz=None): Add system/local timezone Explicit conversion (tz provided): Add specified timezone

Parameters:

Name Type Description Default
tz timezone | None

Optional timezone to add to the naive datetime. If None, uses system local timezone (astimezone()). If provided, uses that specific timezone.

None

Returns:

Type Description
DateTimeTZ

DateTimeTZ instance with timezone-aware datetime

Example
Implicit: add system timezone

aware = naive_dt.add_timezone()

Explicit: add UTC timezone

from datetime import timezone aware_utc = naive_dt.add_timezone(timezone.utc)

Explicit: add JST (+9) timezone

from datetime import timezone, timedelta jst = timezone(timedelta(hours=9)) aware_jst = naive_dt.add_timezone(jst)

Source code in type_bridge/attribute/datetime.py
def add_timezone(self, tz: timezone_type | None = None) -> "DateTimeTZ":
    """Convert DateTime to DateTimeTZ by adding timezone information.

    Implicit conversion (tz=None): Add system/local timezone
    Explicit conversion (tz provided): Add specified timezone

    Args:
        tz: Optional timezone to add to the naive datetime.
            If None, uses system local timezone (astimezone()).
            If provided, uses that specific timezone.

    Returns:
        DateTimeTZ instance with timezone-aware datetime

    Example:
        # Implicit: add system timezone
        aware = naive_dt.add_timezone()

        # Explicit: add UTC timezone
        from datetime import timezone
        aware_utc = naive_dt.add_timezone(timezone.utc)

        # Explicit: add JST (+9) timezone
        from datetime import timezone, timedelta
        jst = timezone(timedelta(hours=9))
        aware_jst = naive_dt.add_timezone(jst)
    """
    from type_bridge.attribute.datetimetz import DateTimeTZ

    dt_value = self.value
    if tz is None:
        # Implicit: add system timezone
        aware_dt = dt_value.astimezone()
    else:
        # Explicit: add specified timezone
        aware_dt = dt_value.replace(tzinfo=tz)

    return DateTimeTZ(aware_dt)

__add__

__add__(other)

Add a Duration to this DateTime.

Parameters:

Name Type Description Default
other Any

A Duration to add to this datetime

required

Returns:

Type Description
DateTime

New DateTime with the duration added

Example

from type_bridge import Duration dt = DateTime(datetime(2024, 1, 31, 14, 0, 0)) duration = Duration("P1M") result = dt + duration # DateTime(2024-02-28 14:00:00)

Source code in type_bridge/attribute/datetime.py
def __add__(self, other: Any) -> "DateTime":
    """Add a Duration to this DateTime.

    Args:
        other: A Duration to add to this datetime

    Returns:
        New DateTime with the duration added

    Example:
        from type_bridge import Duration
        dt = DateTime(datetime(2024, 1, 31, 14, 0, 0))
        duration = Duration("P1M")
        result = dt + duration  # DateTime(2024-02-28 14:00:00)
    """
    from type_bridge.attribute.duration import Duration

    if isinstance(other, Duration):
        # Add duration to datetime
        # Use isodate's add_duration which handles month/day arithmetic

        new_dt = self.value + other.value
        return DateTime(new_dt)
    return NotImplemented

__radd__

__radd__(other)

Reverse addition for Duration + DateTime.

Source code in type_bridge/attribute/datetime.py
def __radd__(self, other: Any) -> "DateTime":
    """Reverse addition for Duration + DateTime."""
    return self.__add__(other)

DateTimeTZ

DateTimeTZ(value)

Bases: Attribute

DateTimeTZ attribute type that accepts timezone-aware datetime values.

This maps to TypeDB's 'datetime-tz' type, which requires timezone information. The datetime must have tzinfo set (e.g., using datetime.timezone.utc or zoneinfo).

Example

from datetime import datetime, timezone

class CreatedAt(DateTimeTZ): pass

Usage with timezone

event = Event(created_at=CreatedAt(datetime(2024, 1, 15, 10, 30, 45, tzinfo=timezone.utc)))

Convert to DateTime

naive_dt = created_at.strip_timezone() # Implicit: just strip tz naive_dt_jst = created_at.strip_timezone(timezone(timedelta(hours=9))) # Explicit: convert to JST, then strip

Initialize DateTimeTZ attribute with a timezone-aware datetime value.

Parameters:

Name Type Description Default
value datetime

The timezone-aware datetime value to store

required

Raises:

Type Description
ValueError

If the datetime does not have timezone information

Source code in type_bridge/attribute/datetimetz.py
def __init__(self, value: datetime_type):
    """Initialize DateTimeTZ attribute with a timezone-aware datetime value.

    Args:
        value: The timezone-aware datetime value to store

    Raises:
        ValueError: If the datetime does not have timezone information
    """
    if value.tzinfo is None:
        raise ValueError(
            "DateTimeTZ requires timezone-aware datetime. "
            "Use DateTime for naive datetime or add tzinfo (e.g., datetime.timezone.utc)"
        )
    super().__init__(value)

value property

value

Get the stored datetime value.

strip_timezone

strip_timezone(tz=None)

Convert DateTimeTZ to DateTime by stripping timezone information.

Implicit conversion (tz=None): Just strip timezone as-is Explicit conversion (tz provided): Convert to specified timezone first, then strip

Parameters:

Name Type Description Default
tz timezone | None

Optional timezone to convert to before stripping. If None, strips timezone without conversion. If provided, converts to that timezone first.

None

Returns:

Type Description
DateTime

DateTime instance with naive datetime

Example
Implicit: strip timezone as-is

naive = dt_tz.strip_timezone()

Explicit: convert to JST (+9), then strip

from datetime import timezone, timedelta jst = timezone(timedelta(hours=9)) naive_jst = dt_tz.strip_timezone(jst)

Source code in type_bridge/attribute/datetimetz.py
def strip_timezone(self, tz: timezone_type | None = None) -> "DateTime":
    """Convert DateTimeTZ to DateTime by stripping timezone information.

    Implicit conversion (tz=None): Just strip timezone as-is
    Explicit conversion (tz provided): Convert to specified timezone first, then strip

    Args:
        tz: Optional timezone to convert to before stripping.
            If None, strips timezone without conversion.
            If provided, converts to that timezone first.

    Returns:
        DateTime instance with naive datetime

    Example:
        # Implicit: strip timezone as-is
        naive = dt_tz.strip_timezone()

        # Explicit: convert to JST (+9), then strip
        from datetime import timezone, timedelta
        jst = timezone(timedelta(hours=9))
        naive_jst = dt_tz.strip_timezone(jst)
    """
    from type_bridge.attribute.datetime import DateTime

    dt_value = self.value
    if tz is not None:
        # Explicit: convert to specified timezone first
        dt_value = dt_value.astimezone(tz)

    # Strip timezone info
    naive_dt = dt_value.replace(tzinfo=None)
    return DateTime(naive_dt)

__add__

__add__(other)

Add a Duration to this DateTimeTZ.

Parameters:

Name Type Description Default
other Any

A Duration to add to this timezone-aware datetime

required

Returns:

Type Description
DateTimeTZ

New DateTimeTZ with the duration added

Note

Duration addition respects timezone changes (DST, etc.)

Example

from type_bridge import Duration from datetime import datetime, timezone dt = DateTimeTZ(datetime(2024, 1, 31, 14, 0, 0, tzinfo=timezone.utc)) duration = Duration("P1M") result = dt + duration # DateTimeTZ(2024-02-28 14:00:00+00:00)

Source code in type_bridge/attribute/datetimetz.py
def __add__(self, other: Any) -> "DateTimeTZ":
    """Add a Duration to this DateTimeTZ.

    Args:
        other: A Duration to add to this timezone-aware datetime

    Returns:
        New DateTimeTZ with the duration added

    Note:
        Duration addition respects timezone changes (DST, etc.)

    Example:
        from type_bridge import Duration
        from datetime import datetime, timezone
        dt = DateTimeTZ(datetime(2024, 1, 31, 14, 0, 0, tzinfo=timezone.utc))
        duration = Duration("P1M")
        result = dt + duration  # DateTimeTZ(2024-02-28 14:00:00+00:00)
    """
    from type_bridge.attribute.duration import Duration

    if isinstance(other, Duration):
        # Add duration to timezone-aware datetime
        # isodate handles timezone-aware datetime + duration correctly
        new_dt = self.value + other.value
        return DateTimeTZ(new_dt)
    return NotImplemented

__radd__

__radd__(other)

Reverse addition for Duration + DateTimeTZ.

Source code in type_bridge/attribute/datetimetz.py
def __radd__(self, other: Any) -> "DateTimeTZ":
    """Reverse addition for Duration + DateTimeTZ."""
    return self.__add__(other)

Decimal

Decimal(value)

Bases: NumericAttribute

Decimal attribute type that accepts fixed-point decimal values.

This maps to TypeDB's 'decimal' type, which is a fixed-point signed decimal number with 64 bits to the left of the decimal point and 19 decimal digits of precision after the point.

Range: −2^63 to 2^63 − 10^−19 (inclusive)

Example

from decimal import Decimal as DecimalType

class AccountBalance(Decimal): pass

class Price(Decimal): pass

Usage with decimal values

balance = AccountBalance(DecimalType("1234.567890")) price = Price(DecimalType("0.02"))

Initialize Decimal attribute with a decimal value.

Parameters:

Name Type Description Default
value Decimal | str | int | float

The decimal value to store. Can be: - decimal.Decimal instance - str that can be parsed as decimal - int or float (will be converted to Decimal)

required
Example

from decimal import Decimal as DecimalType

From Decimal

balance = AccountBalance(DecimalType("123.45"))

balance = AccountBalance("123.45")

From int or float (may lose precision)

balance = AccountBalance(123.45)

Source code in type_bridge/attribute/decimal.py
def __init__(self, value: DecimalType | str | int | float):
    """Initialize Decimal attribute with a decimal value.

    Args:
        value: The decimal value to store. Can be:
            - decimal.Decimal instance
            - str that can be parsed as decimal
            - int or float (will be converted to Decimal)

    Example:
        from decimal import Decimal as DecimalType

        # From Decimal
        balance = AccountBalance(DecimalType("123.45"))

        # From string (recommended for precision)
        balance = AccountBalance("123.45")

        # From int or float (may lose precision)
        balance = AccountBalance(123.45)
    """
    if not isinstance(value, DecimalType):
        value = DecimalType(str(value))
    super().__init__(value)

value property

value

Get the stored decimal value.

Double

Double(value)

Bases: NumericAttribute

Double precision float attribute type that accepts float values.

Example

class Price(Double): pass

class Score(Double): pass

Initialize Double attribute with a float value.

Parameters:

Name Type Description Default
value float

The float value to store

required

Raises:

Type Description
ValueError

If value violates range_constraint

Source code in type_bridge/attribute/double.py
def __init__(self, value: float):
    """Initialize Double attribute with a float value.

    Args:
        value: The float value to store

    Raises:
        ValueError: If value violates range_constraint
    """
    float_value = float(value)

    # Check range constraint if defined on the class
    range_constraint = getattr(self.__class__, "range_constraint", None)
    if range_constraint is not None:
        range_min, range_max = range_constraint
        if range_min is not None:
            min_val = float(range_min)
            if float_value < min_val:
                raise ValueError(
                    f"{self.__class__.__name__} value {float_value} is below minimum {min_val}"
                )
        if range_max is not None:
            max_val = float(range_max)
            if float_value > max_val:
                raise ValueError(
                    f"{self.__class__.__name__} value {float_value} is above maximum {max_val}"
                )

    super().__init__(float_value)

value property

value

Get the stored float value.

__float__

__float__()

Convert to float.

Source code in type_bridge/attribute/double.py
def __float__(self) -> float:
    """Convert to float."""
    return float(self.value)

Duration

Duration(value)

Bases: Attribute

Duration attribute type that accepts ISO 8601 duration values.

This maps to TypeDB's 'duration' type, which represents calendar-aware time spans using months, days, and nanoseconds.

TypeDB duration format: ISO 8601 duration (e.g., P1Y2M3DT4H5M6.789S) Storage: 32-bit months, 32-bit days, 64-bit nanoseconds

Important notes: - Durations are partially ordered (P1M and P30D cannot be compared) - P1D ≠ PT24H (calendar day vs 24 hours) - P1M ≠ P30D (months vary in length) - Addition is not commutative with calendar components

Example

from datetime import timedelta

class SessionDuration(Duration): pass

class EventCadence(Duration): pass

From ISO 8601 string

cadence = EventCadence("P1M") # 1 month interval = SessionDuration("PT1H30M") # 1 hour 30 minutes

From timedelta (converted to Duration internally)

session = SessionDuration(timedelta(hours=2))

Complex duration

complex = EventCadence("P1Y2M3DT4H5M6.789S")

Initialize Duration attribute with a duration value.

Parameters:

Name Type Description Default
value str | timedelta | Duration

The duration value to store. Can be: - str: ISO 8601 duration string (e.g., "P1Y2M3DT4H5M6S") - timedelta: Python timedelta (converted to Duration) - isodate.Duration: Direct Duration object

required

Raises:

Type Description
ValueError

If duration components exceed storage limits

Example

From ISO string

duration1 = Duration("P1M") # 1 month duration2 = Duration("PT1H30M") # 1 hour 30 minutes

From timedelta

from datetime import timedelta duration3 = Duration(timedelta(hours=2, minutes=30))

Complex duration

duration4 = Duration("P1Y2M3DT4H5M6.789S")

Source code in type_bridge/attribute/duration.py
def __init__(self, value: str | timedelta | IsodateDuration):
    """Initialize Duration attribute with a duration value.

    Args:
        value: The duration value to store. Can be:
            - str: ISO 8601 duration string (e.g., "P1Y2M3DT4H5M6S")
            - timedelta: Python timedelta (converted to Duration)
            - isodate.Duration: Direct Duration object

    Raises:
        ValueError: If duration components exceed storage limits

    Example:
        # From ISO string
        duration1 = Duration("P1M")  # 1 month
        duration2 = Duration("PT1H30M")  # 1 hour 30 minutes

        # From timedelta
        from datetime import timedelta
        duration3 = Duration(timedelta(hours=2, minutes=30))

        # Complex duration
        duration4 = Duration("P1Y2M3DT4H5M6.789S")
    """
    if isinstance(value, str):
        value = isodate.parse_duration(value)
    elif isinstance(value, timedelta) and not isinstance(value, IsodateDuration):
        # Convert plain timedelta to Duration for consistent handling
        value = _timedelta_to_duration(value)

    # Validate storage limits
    if isinstance(value, IsodateDuration):
        _validate_duration_limits(value)

    super().__init__(value)

value property

value

Get the stored duration value.

Returns:

Type Description
Duration

isodate.Duration instance (zero duration if None)

to_iso8601

to_iso8601()

Convert duration to ISO 8601 string format.

Returns:

Type Description
str

ISO 8601 duration string (e.g., "P1Y2M3DT4H5M6S")

Example

duration = Duration("P1M") assert duration.to_iso8601() == "P1M"

Source code in type_bridge/attribute/duration.py
def to_iso8601(self) -> str:
    """Convert duration to ISO 8601 string format.

    Returns:
        ISO 8601 duration string (e.g., "P1Y2M3DT4H5M6S")

    Example:
        duration = Duration("P1M")
        assert duration.to_iso8601() == "P1M"
    """
    return isodate.duration_isoformat(self.value)

__add__

__add__(other)

Add two durations.

Parameters:

Name Type Description Default
other Any

Another Duration to add

required

Returns:

Type Description
Duration

New Duration with sum

Example

d1 = Duration("P1M") d2 = Duration("P15D") result = d1 + d2 # P1M15D

Source code in type_bridge/attribute/duration.py
def __add__(self, other: Any) -> "Duration":
    """Add two durations.

    Args:
        other: Another Duration to add

    Returns:
        New Duration with sum

    Example:
        d1 = Duration("P1M")
        d2 = Duration("P15D")
        result = d1 + d2  # P1M15D
    """
    if isinstance(other, Duration):
        # Both are Durations, add their components
        result = self.value + other.value
        return Duration(result)
    return NotImplemented

__radd__

__radd__(other)

Reverse addition for Duration.

Source code in type_bridge/attribute/duration.py
def __radd__(self, other: Any) -> "Duration":
    """Reverse addition for Duration."""
    return self.__add__(other)

__sub__

__sub__(other)

Subtract two durations.

Parameters:

Name Type Description Default
other Any

Another Duration to subtract

required

Returns:

Type Description
Duration

New Duration with difference

Example

d1 = Duration("P1M") d2 = Duration("P15D") result = d1 - d2 # P1M-15D

Source code in type_bridge/attribute/duration.py
def __sub__(self, other: Any) -> "Duration":
    """Subtract two durations.

    Args:
        other: Another Duration to subtract

    Returns:
        New Duration with difference

    Example:
        d1 = Duration("P1M")
        d2 = Duration("P15D")
        result = d1 - d2  # P1M-15D
    """
    if isinstance(other, Duration):
        # Both are Durations, subtract their components
        result = self.value - other.value
        return Duration(result)
    return NotImplemented

AttributeFlags dataclass

AttributeFlags(is_key=False, is_unique=False, card_min=None, card_max=None, has_explicit_card=False, name=None, case=None)

Metadata for attribute ownership and type configuration.

Represents TypeDB ownership annotations like @key, @card(min..max), @unique, and allows overriding the attribute type name with explicit name or case formatting.

Example

class Person(Entity): name: Name = Flag(Key) # @key (implies @card(1..1)) email: Email = Flag(Unique) # @unique @card(1..1) age: Optional[Age] # @card(0..1) - no Flag needed tags: list[Tag] = Flag(Card(min=2)) # @card(2..) jobs: list[Job] = Flag(Card(1, 5)) # @card(1..5)

Override attribute type name explicitly

class Name(String): flags = AttributeFlags(name="name")

Or use case formatting

class PersonName(String): flags = AttributeFlags(case=TypeNameCase.SNAKE_CASE) # -> person_name

to_typeql_annotations

to_typeql_annotations()

Convert to TypeQL annotations like @key, @card(0..5).

Rules: - @key implies @card(1..1), so never output @card with @key - @unique with @card(1..1) is redundant, so omit @card in that case - Otherwise, always output @card if cardinality is specified

Returns:

Type Description
list[str]

List of TypeQL annotation strings

Source code in type_bridge/attribute/flags.py
def to_typeql_annotations(self) -> list[str]:
    """Convert to TypeQL annotations like @key, @card(0..5).

    Rules:
    - @key implies @card(1..1), so never output @card with @key
    - @unique with @card(1..1) is redundant, so omit @card in that case
    - Otherwise, always output @card if cardinality is specified

    Returns:
        List of TypeQL annotation strings
    """
    from type_bridge.typeql.annotations import format_card_annotation

    annotations = []
    if self.is_key:
        annotations.append("@key")
    if self.is_unique:
        annotations.append("@unique")

    # Only output @card if:
    # 1. Not a @key (since @key always implies @card(1..1))
    # 2. Not (@unique with default @card(1..1))
    should_output_card = self.card_min is not None or self.card_max is not None

    if should_output_card and not self.is_key:
        # Check if it's @unique with default (1,1) - if so, omit @card
        is_default_card = self.card_min == 1 and self.card_max == 1
        if not (self.is_unique and is_default_card):
            card_annotation = format_card_annotation(self.card_min, self.card_max)
            if card_annotation:
                annotations.append(card_annotation)

    return annotations

Card

Card(*args, min=None, max=None)

Cardinality marker for multi-value attribute ownership.

IMPORTANT: Card() should only be used with list[Type] annotations. For optional single values, use Optional[Type] instead.

Parameters:

Name Type Description Default
min int | None

Minimum cardinality (default: None, which means unspecified)

None
max int | None

Maximum cardinality (default: None, which means unbounded)

None

Examples:

tags: list[Tag] = Flag(Card(min=2)) # @card(2..) - at least two jobs: list[Job] = Flag(Card(1, 5)) # @card(1..5) - one to five ids: list[ID] = Flag(Key, Card(min=1)) # @key @card(1..)

INCORRECT - use Optional[Type] instead:

age: Age = Flag(Card(min=0, max=1)) # ❌ Wrong!

age: Optional[Age] # ✓ Correct

Initialize cardinality marker.

Supports both positional and keyword arguments: - Card(1, 5) → min=1, max=5 - Card(min=2) → min=2, max=None (unbounded) - Card(max=5) → min=0, max=5 (defaults min to 0) - Card(min=0, max=10) → min=0, max=10

Source code in type_bridge/attribute/flags.py
def __init__(self, *args: int, min: int | None = None, max: int | None = None):
    """Initialize cardinality marker.

    Supports both positional and keyword arguments:
    - Card(1, 5) → min=1, max=5
    - Card(min=2) → min=2, max=None (unbounded)
    - Card(max=5) → min=0, max=5 (defaults min to 0)
    - Card(min=0, max=10) → min=0, max=10
    """
    self.min: int | None = None
    self.max: int | None = None
    if args:
        # Positional arguments: Card(1, 5) or Card(2)
        if len(args) == 1:
            self.min = args[0]
            self.max = max  # Use keyword arg if provided
        elif len(args) == 2:
            self.min = args[0]
            self.max = args[1]
        else:
            raise ValueError("Card accepts at most 2 positional arguments")
    else:
        # Keyword arguments only
        # If only max is specified, default min to 0
        if min is None and max is not None:
            self.min = 0
            self.max = max
        else:
            self.min = min
            self.max = max

TypeFlags dataclass

TypeFlags(name=None, abstract=False, base=False, case=CLASS_NAME)

Metadata flags for Entity and Relation classes.

Parameters:

Name Type Description Default
name str | None

TypeDB type name (if None, uses class name with case formatting)

None
abstract bool

Whether this is an abstract type

False
base bool

Whether this is a Python base class that should not appear in TypeDB schema

False
case TypeNameCase

Case formatting for auto-generated type names (default: CLASS_NAME)

CLASS_NAME
Example

class Person(Entity): flags = TypeFlags(name="person") name: Name

class PersonName(Entity): flags = TypeFlags() # → PersonName (default CLASS_NAME) name: Name

class PersonName(Entity): flags = TypeFlags(case=TypeNameCase.SNAKE_CASE) # → person_name name: Name

class AbstractPerson(Entity): flags = TypeFlags(abstract=True) name: Name

class BaseEntity(Entity): flags = TypeFlags(base=True) # Python base class only # Children skip this in TypeDB hierarchy

Initialize TypeFlags.

Parameters:

Name Type Description Default
name str | None

TypeDB type name (if None, uses class name with case formatting)

None
abstract bool

Whether this is an abstract type

False
base bool

Whether this is a Python base class that should not appear in TypeDB schema

False
case TypeNameCase

Case formatting for auto-generated type names (default: CLASS_NAME)

CLASS_NAME
Source code in type_bridge/attribute/flags.py
def __init__(
    self,
    name: str | None = None,
    abstract: bool = False,
    base: bool = False,
    case: TypeNameCase = TypeNameCase.CLASS_NAME,
):
    """Initialize TypeFlags.

    Args:
        name: TypeDB type name (if None, uses class name with case formatting)
        abstract: Whether this is an abstract type
        base: Whether this is a Python base class that should not appear in TypeDB schema
        case: Case formatting for auto-generated type names (default: CLASS_NAME)
    """
    self.name = name
    self.abstract = abstract
    self.base = base
    self.case = case

TypeNameCase

Bases: Enum

Type name case formatting options for Entity and Relation types.

Options

LOWERCASE: Convert class name to lowercase (default) Example: PersonName → personname CLASS_NAME: Keep class name as-is (PascalCase) Example: PersonName → PersonName SNAKE_CASE: Convert class name to snake_case Example: PersonName → person_name

Integer

Integer(value)

Bases: NumericAttribute

Integer attribute type that accepts int values.

Example

class Age(Integer): pass

class Count(Integer): pass

With Literal for type safety

class Priority(Integer): pass

priority: Literal[1, 2, 3] | Priority

Initialize Integer attribute with an integer value.

Parameters:

Name Type Description Default
value int

The integer value to store

required

Raises:

Type Description
ValueError

If value violates range_constraint

Source code in type_bridge/attribute/integer.py
def __init__(self, value: int):
    """Initialize Integer attribute with an integer value.

    Args:
        value: The integer value to store

    Raises:
        ValueError: If value violates range_constraint
    """
    int_value = int(value)

    # Check range constraint if defined on the class
    range_constraint = getattr(self.__class__, "range_constraint", None)
    if range_constraint is not None:
        range_min, range_max = range_constraint
        if range_min is not None:
            min_val = int(range_min)
            if int_value < min_val:
                raise ValueError(
                    f"{self.__class__.__name__} value {int_value} is below minimum {min_val}"
                )
        if range_max is not None:
            max_val = int(range_max)
            if int_value > max_val:
                raise ValueError(
                    f"{self.__class__.__name__} value {int_value} is above maximum {max_val}"
                )

    super().__init__(int_value)

value property

value

Get the stored integer value.

__int__

__int__()

Convert to int.

Source code in type_bridge/attribute/integer.py
def __int__(self) -> int:
    """Convert to int."""
    return int(self.value)

String

String(value)

Bases: Attribute

String attribute type that accepts str values.

Example

class Name(String): pass

class Email(String): pass

With Literal for type safety

class Status(String): pass

status: Literal["active", "inactive"] | Status

Initialize String attribute with a string value.

Parameters:

Name Type Description Default
value str

The string value to store

required
Source code in type_bridge/attribute/string.py
def __init__(self, value: str):
    """Initialize String attribute with a string value.

    Args:
        value: The string value to store
    """
    super().__init__(value)

value property

value

Get the stored string value.

__str__

__str__()

Convert to string.

Source code in type_bridge/attribute/string.py
def __str__(self) -> str:
    """Convert to string."""
    return str(self.value)

__add__

__add__(other)

Concatenate strings.

Source code in type_bridge/attribute/string.py
def __add__(self, other: object) -> "String":
    """Concatenate strings."""
    if isinstance(other, str):
        return String(self.value + other)
    elif isinstance(other, String):
        return String(self.value + other.value)
    else:
        return NotImplemented

__radd__

__radd__(other)

Right-hand string concatenation.

Source code in type_bridge/attribute/string.py
def __radd__(self, other: object) -> "String":
    """Right-hand string concatenation."""
    if isinstance(other, str):
        return String(other + self.value)
    else:
        return NotImplemented

contains classmethod

contains(value)

Create contains string expression.

Parameters:

Name Type Description Default
value String

String value to search for

required

Returns:

Type Description
StringExpr

StringExpr for attr contains value

Example

Email.contains(Email("@company.com")) # email contains "@company.com"

Source code in type_bridge/attribute/string.py
@classmethod
def contains(cls, value: "String") -> "StringExpr":
    """Create contains string expression.

    Args:
        value: String value to search for

    Returns:
        StringExpr for attr contains value

    Example:
        Email.contains(Email("@company.com"))  # email contains "@company.com"
    """
    from type_bridge.expressions import StringExpr

    return StringExpr(attr_type=cls, operation="contains", pattern=value)

like classmethod

like(pattern)

Create regex pattern matching expression.

Parameters:

Name Type Description Default
pattern String

Regex pattern to match

required

Returns:

Type Description
StringExpr

StringExpr for attr like pattern

Example

Name.like(Name("^A.*")) # name starts with 'A'

Source code in type_bridge/attribute/string.py
@classmethod
def like(cls, pattern: "String") -> "StringExpr":
    """Create regex pattern matching expression.

    Args:
        pattern: Regex pattern to match

    Returns:
        StringExpr for attr like pattern

    Example:
        Name.like(Name("^A.*"))  # name starts with 'A'
    """
    from type_bridge.expressions import StringExpr

    return StringExpr(attr_type=cls, operation="like", pattern=pattern)

regex classmethod

regex(pattern)

Create regex pattern matching expression (alias for like).

Note

Automatically converts to TypeQL 'like' operator. Both 'like' and 'regex' perform regex pattern matching in TypeDB.

Parameters:

Name Type Description Default
pattern String

Regex pattern to match

required

Returns:

Type Description
StringExpr

StringExpr for attr like pattern

Example

Email.regex(Email(".@gmail.com")) # Generates TypeQL: $email like ".@gmail.com"

Source code in type_bridge/attribute/string.py
@classmethod
def regex(cls, pattern: "String") -> "StringExpr":
    """Create regex pattern matching expression (alias for like).

    Note:
        Automatically converts to TypeQL 'like' operator.
        Both 'like' and 'regex' perform regex pattern matching in TypeDB.

    Args:
        pattern: Regex pattern to match

    Returns:
        StringExpr for attr like pattern

    Example:
        Email.regex(Email(".*@gmail\\.com"))  # Generates TypeQL: $email like ".*@gmail\\.com"
    """
    from type_bridge.expressions import StringExpr

    return StringExpr(attr_type=cls, operation="regex", pattern=pattern)

startswith classmethod

startswith(prefix)

Create startswith string expression.

Parameters:

Name Type Description Default
prefix String

Prefix string to check for

required

Returns:

Type Description
StringExpr

StringExpr for attr like "^prefix.*"

Source code in type_bridge/attribute/string.py
@classmethod
def startswith(cls, prefix: "String") -> "StringExpr":
    """Create startswith string expression.

    Args:
        prefix: Prefix string to check for

    Returns:
        StringExpr for attr like "^prefix.*"
    """
    # Unwrap if it's an Attribute instance to get the raw string for regex construction
    # Note: Type-safe signature says "String", but we need the raw value
    raw_prefix = prefix.value if isinstance(prefix, String) else str(prefix)
    pattern = f"^{re.escape(raw_prefix)}.*"
    return cls.regex(cls(pattern))

endswith classmethod

endswith(suffix)

Create endswith string expression.

Parameters:

Name Type Description Default
suffix String

Suffix string to check for

required

Returns:

Type Description
StringExpr

StringExpr for attr like ".*suffix$"

Source code in type_bridge/attribute/string.py
@classmethod
def endswith(cls, suffix: "String") -> "StringExpr":
    """Create endswith string expression.

    Args:
        suffix: Suffix string to check for

    Returns:
        StringExpr for attr like ".*suffix$"
    """
    # Unwrap if it's an Attribute instance to get the raw string for regex construction
    raw_suffix = suffix.value if isinstance(suffix, String) else str(suffix)
    pattern = f".*{re.escape(raw_suffix)}$"
    return cls.regex(cls(pattern))

build_lookup classmethod

build_lookup(lookup, value)

Build an expression for string-specific lookups.

Overrides base method to handle contains, regex, startswith, endswith.

Source code in type_bridge/attribute/string.py
@classmethod
def build_lookup(cls, lookup: str, value: Any) -> "Expression":
    """Build an expression for string-specific lookups.

    Overrides base method to handle contains, regex, startswith, endswith.
    """
    if lookup in ("contains", "regex", "startswith", "endswith", "like"):
        # Ensure value is wrapped in String for method calls
        wrapped_val = value if isinstance(value, cls) else cls(str(value))

        if lookup == "contains":
            return cls.contains(wrapped_val)
        elif lookup == "regex" or lookup == "like":
            return cls.regex(wrapped_val)
        elif lookup == "startswith":
            return cls.startswith(wrapped_val)
        elif lookup == "endswith":
            return cls.endswith(wrapped_val)

    # Delegate to base for standard operators (eq, in, isnull, etc.)
    return super().build_lookup(lookup, value)

Flag

Flag(*annotations)

Create attribute flags for Key, Unique, and Card markers.

Usage

field: Type = Flag(Key) # @key (implies @card(1..1)) field: Type = Flag(Unique) # @unique @card(1..1) field: list[Type] = Flag(Card(min=2)) # @card(2..) field: list[Type] = Flag(Card(1, 5)) # @card(1..5) field: Type = Flag(Key, Unique) # @key @unique field: list[Type] = Flag(Key, Card(min=1)) # @key @card(1..)

For optional single values, use Optional[Type] instead: field: Optional[Type] # @card(0..1) - no Flag needed

Parameters:

Name Type Description Default
*annotations Any

Variable number of Key, Unique, or Card marker instances

()

Returns:

Type Description
Annotated[Any, AttributeFlags]

AttributeFlags instance with the specified flags

Example

class Person(Entity): flags = TypeFlags(name="person") name: Name = Flag(Key) # @key (implies @card(1..1)) email: Email = Flag(Key, Unique) # @key @unique age: Optional[Age] # @card(0..1) tags: list[Tag] = Flag(Card(min=2)) # @card(2..) jobs: list[Job] = Flag(Card(1, 5)) # @card(1..5)

Source code in type_bridge/attribute/flags.py
def Flag(*annotations: Any) -> Annotated[Any, AttributeFlags]:
    """Create attribute flags for Key, Unique, and Card markers.

    Usage:
        field: Type = Flag(Key)                   # @key (implies @card(1..1))
        field: Type = Flag(Unique)                # @unique @card(1..1)
        field: list[Type] = Flag(Card(min=2))     # @card(2..)
        field: list[Type] = Flag(Card(1, 5))      # @card(1..5)
        field: Type = Flag(Key, Unique)           # @key @unique
        field: list[Type] = Flag(Key, Card(min=1)) # @key @card(1..)

    For optional single values, use Optional[Type] instead:
        field: Optional[Type]  # @card(0..1) - no Flag needed

    Args:
        *annotations: Variable number of Key, Unique, or Card marker instances

    Returns:
        AttributeFlags instance with the specified flags

    Example:
        class Person(Entity):
            flags = TypeFlags(name="person")
            name: Name = Flag(Key)                    # @key (implies @card(1..1))
            email: Email = Flag(Key, Unique)          # @key @unique
            age: Optional[Age]                        # @card(0..1)
            tags: list[Tag] = Flag(Card(min=2))       # @card(2..)
            jobs: list[Job] = Flag(Card(1, 5))        # @card(1..5)
    """
    flags = AttributeFlags()
    has_card = False

    for ann in annotations:
        if ann is Key:
            flags.is_key = True
        elif ann is Unique:
            flags.is_unique = True
        elif isinstance(ann, Card):
            # Extract cardinality from Card instance
            flags.card_min = ann.min
            flags.card_max = ann.max
            flags.has_explicit_card = True
            has_card = True

    # If Key was used but no Card, set default card(1,1)
    if flags.is_key and not has_card:
        flags.card_min = 1
        flags.card_max = 1

    return flags