Skip to content

Relationship

pylpg.relationship

Relationship classes and descriptors for graph edges.

Classes:

Name Description
BoundRelationship

A relationship descriptor bound to a specific node instance.

Direction

Direction of a relationship traversal.

Relationship

Base class for graph relationships.

RelationshipDescriptor

Descriptor that declares a relationship on a Node class.

RelationshipFrom

Declares an incoming relationship on a Node class.

RelationshipTo

Declares an outgoing relationship on a Node class.

RelationshipUndirected

Declares an undirected relationship on a Node class.

BoundRelationship

BoundRelationship(owner: Node, descriptor: RelationshipDescriptor)

A relationship descriptor bound to a specific node instance.

Provides all() to traverse and connect() to create relationships.

Methods:

Name Description
all

Return all nodes connected to the owner via this relationship.

connect

Create and save a relationship from the owner to target_node.

relationships

Return the relationships connecting the owner to those nodes.

Source code in src/pylpg/relationship.py
def __init__(
    self,
    owner: pylpg.node.Node,
    descriptor: "RelationshipDescriptor",
) -> None:
    self._owner = owner
    self._descriptor = descriptor

all

all() -> list[Node]

Return all nodes connected to the owner via this relationship.

Source code in src/pylpg/relationship.py
def all(self) -> list[pylpg.node.Node]:
    """Return all nodes connected to the owner via this relationship."""
    return [target for (target, _) in self._traverse()]

connect

connect(target_node: Node, **properties: Any) -> None

Create and save a relationship from the owner to target_node.

Example
session.save(alice)
session.save(bob)
alice.friends.connect(bob, since="2024")
Source code in src/pylpg/relationship.py
def connect(self, target_node: pylpg.node.Node, **properties: typing.Any) -> None:
    """Create and save a relationship from the owner to target_node.

    Example:
        ```python
        session.save(alice)
        session.save(bob)
        alice.friends.connect(bob, since="2024")
        ```
    """
    session = self._get_session()
    if self._descriptor._direction == Direction.INCOMING:
        (source, target) = (target_node, self._owner)
    else:
        (source, target) = (self._owner, target_node)
    relationship = self._descriptor._relationship_class(
        source=source,
        target=target,
        **properties,
    )
    session.save(relationship)

relationships

relationships() -> list[Relationship]

Return the relationships connecting the owner to those nodes.

Each relationship carries its properties, its source and its target. all() and relationships() are separate queries whose results are not necessarily in the same order, so they must not be paired up by position.

Example
for relationship in box.items.relationships():
    print(relationship.order, relationship.target)
Source code in src/pylpg/relationship.py
def relationships(self) -> list[Relationship]:
    """Return the relationships connecting the owner to those nodes.

    Each relationship carries its properties, its source and its target.
    `all()` and `relationships()` are separate queries whose results are
    not necessarily in the same order, so they must not be paired up by
    position.

    Example:
        ```python
        for relationship in box.items.relationships():
            print(relationship.order, relationship.target)
        ```
    """
    relationship_class = self._descriptor._relationship_class
    relationships = []
    for target, deserialized_relationship in self._traverse():
        properties = {
            key: value
            for key, value in deserialized_relationship.items()
            if key in relationship_class.__primitive_properties__
        }
        if deserialized_relationship["_start_id"] == self._owner._database_id:
            (source, relationship_target) = (self._owner, target)
        else:
            (source, relationship_target) = (target, self._owner)
        relationship = relationship_class(
            source=source,
            target=relationship_target,
            **properties,
        )
        relationship._database_id = deserialized_relationship["_database_id"]
        relationships.append(relationship)
    return relationships

Direction

Bases: Enum

Direction of a relationship traversal.

Relationship

Relationship(*, source: Node, target: Node, **kwargs: Any)

Base class for graph relationships.

Subclass Relationship to define relationship types. The __type__ class attribute is required and sets the relationship type in the database.

Example
class Knows(Relationship):
    __type__ = "KNOWS"
    since: str | None = None

Methods:

Name Description
is_saved

Return True if this relationship has been saved to the database.

to_dict

Return primitive properties as a dict, excluding None values.

Source code in src/pylpg/relationship.py
def __init__(
    self,
    *,
    source: pylpg.node.Node,
    target: pylpg.node.Node,
    **kwargs: typing.Any,
) -> None:
    self._database_id = None
    self._temp_id = uuid.uuid4().hex
    self.source = source
    self.target = target
    for property_name in self.__primitive_properties__:
        if property_name in kwargs:
            setattr(self, property_name, kwargs[property_name])
        elif not hasattr(type(self), property_name):
            raise ValueError(f"Missing required property: {property_name}")

is_saved

is_saved() -> bool

Return True if this relationship has been saved to the database.

Source code in src/pylpg/relationship.py
def is_saved(self) -> bool:
    """Return True if this relationship has been saved to the database."""
    return self._database_id is not None

to_dict

to_dict() -> dict[str, Any]

Return primitive properties as a dict, excluding None values.

Source code in src/pylpg/relationship.py
def to_dict(self) -> dict[str, typing.Any]:
    """Return primitive properties as a dict, excluding None values."""
    result: dict[str, typing.Any] = {}
    for property_name in self.__primitive_properties__:
        property_value = getattr(self, property_name)
        if property_value is not None:
            result[property_name] = property_value
    return result

RelationshipDescriptor

RelationshipDescriptor(direction: Direction, relationship_class: type[Relationship])

Descriptor that declares a relationship on a Node class.

Use the convenience subclasses RelationshipTo, RelationshipFrom, and RelationshipUndirected instead of this class directly.

Source code in src/pylpg/relationship.py
def __init__(
    self,
    direction: Direction,
    relationship_class: type[Relationship],
) -> None:
    self._direction = direction
    self._relationship_class = relationship_class

RelationshipFrom

RelationshipFrom(relationship_class: type[Relationship])

Bases: RelationshipDescriptor

Declares an incoming relationship on a Node class.

Example
class Person(Node):
    name: str
    known_by = RelationshipFrom(Knows)
Source code in src/pylpg/relationship.py
def __init__(
    self,
    relationship_class: type[Relationship],
) -> None:
    super().__init__(
        direction=Direction.INCOMING,
        relationship_class=relationship_class,
    )

RelationshipTo

RelationshipTo(relationship_class: type[Relationship])

Bases: RelationshipDescriptor

Declares an outgoing relationship on a Node class.

Example
class Person(Node):
    name: str
    friends = RelationshipTo(Knows)
Source code in src/pylpg/relationship.py
def __init__(
    self,
    relationship_class: type[Relationship],
) -> None:
    super().__init__(
        direction=Direction.OUTGOING,
        relationship_class=relationship_class,
    )

RelationshipUndirected

RelationshipUndirected(relationship_class: type[Relationship])

Bases: RelationshipDescriptor

Declares an undirected relationship on a Node class.

Example
class Person(Node):
    name: str
    contacts = RelationshipUndirected(Knows)
Source code in src/pylpg/relationship.py
def __init__(
    self,
    relationship_class: type[Relationship],
) -> None:
    super().__init__(
        direction=Direction.UNDIRECTED,
        relationship_class=relationship_class,
    )