]> git.ipfire.org Git - pbs.git/commitdiff
packages: Move to SQLModel
authorMichael Tremer <michael.tremer@ipfire.org>
Wed, 2 Jul 2025 13:29:10 +0000 (13:29 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Wed, 2 Jul 2025 13:29:10 +0000 (13:29 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/buildservice/packages.py

index 9a6cb9cdd95a42a092b913fb89072be2d1a3edfc..fbb7063ba6cdfd9acc8db8b5712e3f17e071e39f 100644 (file)
@@ -6,11 +6,12 @@ import logging
 import mimetypes
 import os
 import shutil
+import sqlalchemy
+import sqlmodel
 import stat
 
-import sqlalchemy
-from sqlalchemy import Column, Computed, ForeignKey
-from sqlalchemy import ARRAY, BigInteger, Boolean, DateTime, Integer, LargeBinary, Text, UUID
+# Import types
+from uuid import UUID
 from sqlalchemy.dialects.postgresql import TSVECTOR
 
 import pakfire
@@ -260,7 +261,7 @@ class Packages(base.Object):
                return await self.db.fetch_as_list(stmt)
 
 
-class Package(database.Base, database.BackendMixin, database.SoftDeleteMixin):
+class Package(sqlmodel.SQLModel, database.BackendMixin, database.SoftDeleteMixin, table=True):
        __tablename__ = "packages"
 
        def __repr__(self):
@@ -277,11 +278,11 @@ class Package(database.Base, database.BackendMixin, database.SoftDeleteMixin):
 
        # ID
 
-       id = Column(Integer, primary_key=True)
+       id : int = sqlmodel.Field(primary_key=True, exclude=True)
 
        # UUID
 
-       uuid = Column(UUID, nullable=False)
+       uuid: UUID
 
        # Link
 
@@ -291,8 +292,8 @@ class Package(database.Base, database.BackendMixin, database.SoftDeleteMixin):
 
        # Created At
 
-       created_at = Column(
-               DateTime(timezone=False), nullable=False, server_default=sqlalchemy.func.current_timestamp(),
+       created_at : datetime.datetime = sqlmodel.Field(
+               sa_column_kwargs = {"server_default" : sqlalchemy.text("CURRENT_TIMESTAMP")}
        )
 
        async def delete(self, deleted_by=None):
@@ -330,15 +331,15 @@ class Package(database.Base, database.BackendMixin, database.SoftDeleteMixin):
 
        # Name
 
-       name = Column(Text, nullable=False)
+       name: str
 
        # EVR
 
-       evr = Column(Text, nullable=False)
+       evr: str
 
        # Arch
 
-       arch = Column(Text, nullable=False)
+       arch: str
 
        # Source?
 
@@ -356,51 +357,69 @@ class Package(database.Base, database.BackendMixin, database.SoftDeleteMixin):
 
        # Groups
 
-       groups = Column(ARRAY(Text), nullable=False, default=[])
+       groups: list[str] = sqlmodel.Field(
+               sa_column=sqlalchemy.Column(sqlalchemy.ARRAY(sqlalchemy.Text)), default=[],
+       )
 
        # Packager
 
-       packager = Column(Text, nullable=False, default="")
+       packager: str = sqlmodel.Field(default="")
 
        # License
 
-       license = Column(Text, nullable=False)
+       license: str
 
        # URL
 
-       url = Column(Text, nullable=False)
+       url: str
 
        # Summary
 
-       summary = Column(Text, nullable=False)
+       summary: str
 
        # Description
 
-       description = Column(Text, nullable=False)
+       description: str
 
        # Build Arches
 
-       build_arches = Column(ARRAY(Text), nullable=False)
+       build_arches: list[str] = sqlmodel.Field(
+               sa_column=sqlalchemy.Column(sqlalchemy.ARRAY(sqlalchemy.Text)),
+       )
 
        # Size
 
-       size = Column(BigInteger, nullable=False)
+       size: int
 
        # Dependencies
 
-       prerequires = Column(ARRAY(Text), nullable=False, default=[])
+       prerequires: list[str] = sqlmodel.Field(
+               sa_column=sqlalchemy.Column(sqlalchemy.ARRAY(sqlalchemy.Text)), default=[],
+       )
 
-       requires = Column(ARRAY(Text), nullable=False, default=[])
+       requires: list[str] = sqlmodel.Field(
+               sa_column=sqlalchemy.Column(sqlalchemy.ARRAY(sqlalchemy.Text)), default=[],
+       )
 
-       provides = Column(ARRAY(Text), nullable=False, default=[])
+       provides: list[str] = sqlmodel.Field(
+               sa_column=sqlalchemy.Column(sqlalchemy.ARRAY(sqlalchemy.Text)), default=[],
+       )
 
-       conflicts = Column(ARRAY(Text), nullable=False, default=[])
+       conflicts: list[str] = sqlmodel.Field(
+               sa_column=sqlalchemy.Column(sqlalchemy.ARRAY(sqlalchemy.Text)), default=[],
+       )
 
-       obsoletes = Column(ARRAY(Text), nullable=False, default=[])
+       obsoletes: list[str] = sqlmodel.Field(
+               sa_column=sqlalchemy.Column(sqlalchemy.ARRAY(sqlalchemy.Text)), default=[],
+       )
 
-       suggests = Column(ARRAY(Text), nullable=False, default=[])
+       suggests: list[str] = sqlmodel.Field(
+               sa_column=sqlalchemy.Column(sqlalchemy.ARRAY(sqlalchemy.Text)), default=[],
+       )
 
-       recommends = Column(ARRAY(Text), nullable=False, default=[])
+       recommends: list[str] = sqlmodel.Field(
+               sa_column=sqlalchemy.Column(sqlalchemy.ARRAY(sqlalchemy.Text)), default=[],
+       )
 
        # Commit
 
@@ -411,28 +430,27 @@ class Package(database.Base, database.BackendMixin, database.SoftDeleteMixin):
 
        # Distro ID
 
-       distro_id = Column(Integer, ForeignKey("distributions.id"), nullable=False)
+       distro_id: int = sqlmodel.Field(foreign_key="distributions.id")
 
        # Distro
 
-       distro = sqlalchemy.orm.relationship("Distro",
-               foreign_keys=[distro_id], lazy="selectin")
+       distro: "Distro" = sqlmodel.Relationship()
 
        # Build ID
 
-       build_id = Column(UUID)
+       build_id: UUID
 
        # Build Host
 
-       build_host = Column(Text, nullable=False)
+       build_host: str
 
        # Build Time
 
-       build_time = Column(DateTime(timezone=False), nullable=False)
+       build_time: datetime.datetime
 
        # Path
 
-       path = Column(Text)
+       path: str | None
 
        # Download URL
 
@@ -448,15 +466,15 @@ class Package(database.Base, database.BackendMixin, database.SoftDeleteMixin):
 
        # Digest Type
 
-       digest_type = Column(Text, nullable=False)
+       digest_type: str
 
        # Digest
 
-       digest = Column(LargeBinary, nullable=False)
+       digest: bytes = sqlmodel.Field(sa_column=sqlalchemy.Column(sqlalchemy.LargeBinary, nullable=False))
 
        # File Size
 
-       filesize = Column(BigInteger, nullable=False)
+       filesize: int
 
        async def _import_archive(self, archive):
                """
@@ -583,32 +601,35 @@ class Package(database.Base, database.BackendMixin, database.SoftDeleteMixin):
 
        # Search
 
-       search = Column(
-               TSVECTOR, Computed(
-                       """
-                               (
-                                       setweight(
-                                               to_tsvector('simple'::regconfig, name),
-                                               'A'::"char"
+       search: str = sqlmodel.Field(
+               sa_column=sqlalchemy.Column(
+                       TSVECTOR,
+                       sqlmodel.Computed(
+                               """
+                                       (
+                                               setweight(
+                                                       to_tsvector('simple'::regconfig, name),
+                                                       'A'::"char"
+                                               )
+                                               ||
+                                               setweight(
+                                                               to_tsvector('english'::regconfig, summary),
+                                                               'B'::"char"
+                                               )
+                                               ||
+                                               setweight(
+                                                       to_tsvector('english'::regconfig, description),
+                                                       'C'::"char"
+                                               )
                                        )
-                                       ||
-                                       setweight(
-                                               to_tsvector('english'::regconfig, summary),
-                                               'B'::"char"
-                                       )
-                                       ||
-                                       setweight(
-                                               to_tsvector('english'::regconfig, description),
-                                               'C'::"char"
-                                       )
-                               )
-                       """,
-            persisted=True,
-        )
+                               """,
+                               persisted=True,
+                       ),
+               )
        )
 
 
-class File(database.Base):
+class File(sqlmodel.SQLModel, table=True):
        __tablename__ = "package_files"
 
        def __str__(self):
@@ -616,27 +637,27 @@ class File(database.Base):
 
        # Package ID
 
-       pkg_id = Column(Integer, ForeignKey("packages.id"), primary_key=True, nullable=False)
+       pkg_id : int = sqlmodel.Field(primary_key=True, foreign_key="packages.id", exclude=True)
 
        # Package
 
-       package = sqlalchemy.orm.relationship("Package", foreign_keys=[pkg_id], lazy="selectin")
+       package: "Package" = sqlmodel.Relationship()
 
        # Path
 
-       path = Column(Text, primary_key=True, nullable=False)
+       path: str = sqlmodel.Field(primary_key=True)
 
        # Size
 
-       size = Column(BigInteger, nullable=False)
+       size: int
 
        # Config
 
-       config = Column(Boolean, nullable=False, default=False)
+       config: bool = sqlmodel.Field(default=False)
 
        # Mode
 
-       mode = Column(Integer, nullable=False)
+       mode: int
 
        # Type
 
@@ -646,51 +667,65 @@ class File(database.Base):
 
        # uname
 
-       uname = Column(Text, nullable=False)
+       uname: str
 
        # gname
 
-       gname = Column(Text, nullable=False)
+       gname: str
 
        # Creation Time
 
-       ctime = Column(DateTime(timezone=False), nullable=False)
+       ctime: datetime.datetime
 
        # Modification Time
 
-       mtime = Column(DateTime(timezone=False), nullable=False)
+       mtime: datetime.datetime
 
        # MIME Type
 
-       mimetype = Column(Text)
+       mimetype: str | None
 
        # Capabilities
 
-       capabilities = Column(ARRAY(Text))
+       capabilities: list[str] = sqlmodel.Field(
+               sa_column=sqlalchemy.Column(sqlalchemy.ARRAY(sqlalchemy.Text)),
+       )
 
        # Digest SHA-2 512
 
-       digest_sha2_512 = Column(LargeBinary)
+       digest_sha2_512: bytes = sqlmodel.Field(
+               sa_column=sqlalchemy.Column(sqlalchemy.LargeBinary, nullable=False),
+       )
 
        # Digest SHA-2 256
 
-       digest_sha2_256 = Column(LargeBinary)
+       digest_sha2_256: bytes = sqlmodel.Field(
+               sa_column=sqlalchemy.Column(sqlalchemy.LargeBinary, nullable=False),
+       )
 
        # Digest Blake2b512
 
-       digest_blake2b512 = Column(LargeBinary)
+       digest_blake2b512: bytes = sqlmodel.Field(
+               sa_column=sqlalchemy.Column(sqlalchemy.LargeBinary, nullable=False),
+       )
 
        # Digest Blake2s256
 
-       digest_blake2s256 = Column(LargeBinary)
+       digest_blake2s256: bytes = sqlmodel.Field(
+               sa_column=sqlalchemy.Column(sqlalchemy.LargeBinary, nullable=False),
+       )
 
        # Digest SHA-3 512
 
-       digest_sha3_512 = Column(LargeBinary)
+       digest_sha3_512: bytes = sqlmodel.Field(
+               sa_column=sqlalchemy.Column(sqlalchemy.LargeBinary, nullable=False),
+       )
 
        # Digest SHA-3 256
 
-       digest_sha3_256 = Column(LargeBinary)
+       digest_sha3_256: bytes = sqlmodel.Field(
+               sa_column=sqlalchemy.Column(sqlalchemy.LargeBinary, nullable=False),
+       )
 
        # Downloadable?