Commit 7c215f75 authored by Jakob Moser's avatar Jakob Moser
Browse files

Implement Base and Retrievable types

parent 51e18a71
Loading
Loading
Loading
Loading

poolpay/model/Base.py

0 → 100644
+40 −0
Original line number Diff line number Diff line
from __future__ import annotations

from uuid import UUID, uuid4

from sqlalchemy.orm import Mapped, mapped_column

from poolpay.model.InvalidUuidError import InvalidUuidError
from poolpay.model.Retrievable import Retrievable
from poolpay.model.Uuid import Uuid


class Base(Retrievable):
    """
    A type with a UUID, stored in the database.

    It also has a method to return a dictionary representation for easy serialization.
    """

    # See https://docs.sqlalchemy.org/en/20/orm/declarative_config.html#abstract
    __abstract__ = True

    uuid: Mapped[UUID] = mapped_column(Uuid(), primary_key=True, default=uuid4)

    @classmethod
    def get_only(cls, uuid: str | UUID) -> Base | None:
        if isinstance(uuid, str):
            try:
                # Manually convert the uuid to a UUID object (even though sqlalchemy-uuid would do that
                # automatically for us), so we can catch errors.
                uuid_obj = UUID(uuid)
            except ValueError:
                raise InvalidUuidError()
        else:
            uuid_obj = uuid

        return super().get_only(uuid_obj)

    @property
    def primary_key(self) -> UUID:
        return self.uuid
+53 −0
Original line number Diff line number Diff line
from __future__ import annotations

from typing import Any

from sqlalchemy.orm import DeclarativeBase, MappedColumn

from poolpay import db


class Retrievable(DeclarativeBase):
    """
    A type whose instances can be retrieved from the database.

    It has methods to get all instances and a specific instance by its primary key.
    """

    # See https://docs.sqlalchemy.org/en/20/orm/declarative_config.html#abstract
    __abstract__ = True

    @classmethod
    def get_canonical_order_column(cls) -> MappedColumn | None:
        """
        Return the colum by which instances of this type should be canonically ordered
        when retrieving them all from the database.

        By default, the column is None, i.e. no order is enforced.
        """
        return None

    @classmethod
    def get_all(cls) -> list[Retrievable]:
        """
        Return all instances of this type.
        """
        return db.session.execute(
            db.select(cls).order_by(cls.get_canonical_order_column())
        ).scalars()

    @classmethod
    def get_only(cls, primary_key: Any) -> Retrievable | None:
        """
        Return the instance of this type with the given primary key or None if it doesn't exist.
        """
        return db.session.get(cls, primary_key)

    @property
    def primary_key(self) -> Any:
        """
        Return the primary key that can be used to identify an instance of this class.
        """
        raise NotImplementedError(
            "The primary key property needs to be implemented by subclasses."
        )