Coverage for postrfp / model / datafeeds.py: 100%
16 statements
« prev ^ index » next coverage.py v7.12.0, created at 2025-12-03 01:35 +0000
« prev ^ index » next coverage.py v7.12.0, created at 2025-12-03 01:35 +0000
1from typing import Optional, TYPE_CHECKING
3import sqids
4from sqlalchemy import (
5 ForeignKey,
6 VARCHAR,
7)
8from sqlalchemy.orm import Mapped, mapped_column, relationship
11from postrfp.model.meta import Base, HTTPHeadersMixin, SqidsMixin
13if TYPE_CHECKING:
14 from postrfp.model.humans import Organisation
15 from postrfp.model.jobs import JobExecution
18SQID = sqids.Sqids(
19 alphabet="qu42jfwe8apgxz9d7shym5ckvb6nrt3",
20 min_length=5,
21)
24class Datafeed(Base, HTTPHeadersMixin, SqidsMixin):
25 """
26 Configuration for fetching external data and mapping it to Content items.
27 """
29 __tablename__ = "datafeeds"
30 _sqids_alphabet = "qu42jfwe8apgxz9d7shym5ckvb6nrt3"
32 org_id: Mapped[str] = mapped_column(
33 VARCHAR(length=50),
34 ForeignKey("organisations.id", ondelete="CASCADE", onupdate="CASCADE"),
35 nullable=False,
36 index=True,
37 )
39 name: Mapped[str] = mapped_column(VARCHAR(length=128), nullable=False)
41 description: Mapped[Optional[str]] = mapped_column(
42 VARCHAR(length=512), nullable=True
43 )
45 source_url: Mapped[str] = mapped_column(
46 VARCHAR(length=512),
47 nullable=False,
48 comment="External URL to fetch data from. Supports templating (e.g. {project_id})",
49 )
51 transform_expression: Mapped[Optional[str]] = mapped_column(
52 VARCHAR(length=4000),
53 nullable=True,
54 comment="CEL expression to transform external JSON to Content format",
55 )
57 # Relationships
58 organisation: Mapped["Organisation"] = relationship("Organisation")
60 executions: Mapped[list["JobExecution"]] = relationship(
61 "JobExecution", back_populates="datafeed", cascade="all, delete-orphan"
62 )
64 def __repr__(self) -> str:
65 return f"<Datafeed {self.name} ({self.id})>"