commit:     01d5398cd23ce2bc930694ecfa62408b87bd2ddb
Author:     Magnus Granberg <zorry <AT> gentoo <DOT> org>
AuthorDate: Wed Oct 30 21:43:44 2024 +0000
Commit:     Magnus Granberg <zorry <AT> gentoo <DOT> org>
CommitDate: Wed Oct 30 21:43:44 2024 +0000
URL:        
https://gitweb.gentoo.org/proj/tinderbox-cluster.git/commit/?id=01d5398c

Update db to support Buildbot 4.1.0

Signed-off-by: Magnus Granberg <zorry <AT> gentoo.org>

 buildbot_gentoo_ci/db/builds.py    | 184 +++++++++++++++++++++++--------------
 buildbot_gentoo_ci/db/connector.py |   6 +-
 buildbot_gentoo_ci/db/model.py     |  55 ++++-------
 buildbot_gentoo_ci/db/packages.py  | 113 +++++++++++++++--------
 buildbot_gentoo_ci/db/versions.py  | 174 ++++++++++++++++++++++-------------
 5 files changed, 318 insertions(+), 214 deletions(-)

diff --git a/buildbot_gentoo_ci/db/builds.py b/buildbot_gentoo_ci/db/builds.py
index 21adcc0..47413a3 100644
--- a/buildbot_gentoo_ci/db/builds.py
+++ b/buildbot_gentoo_ci/db/builds.py
@@ -15,7 +15,11 @@
 # Copyright Buildbot Team Members
 # Origins: buildbot.db.*
 # Modifyed by Gentoo Authors.
-# Copyright 2023 Gentoo Authors
+# Copyright 2024 Gentoo Authors
+
+from __future__ import annotations
+from dataclasses import dataclass
+from typing import TYPE_CHECKING
 
 import uuid
 import sqlalchemy as sa
@@ -23,94 +27,134 @@ import sqlalchemy as sa
 from twisted.internet import defer
 
 from buildbot.db import base
+from buildbot.warnings import warn_deprecated
+
+if TYPE_CHECKING:
+    import datetime
+
+@dataclass
+class ProjectsBuildsModel:
+    id : int
+    build_id : int
+    project_uuid : str
+    version_uuid : str
+    buildbot_build_id : int
+    bug_id : int
+    status : str
+    requested : bool
+    created_at : datetime.datetime | None
+    updated_at : datetime.datetime | None
+    deleted : bool
+    deleted_at: datetime.datetime | None
+
+    # For backward compatibility
+    def __getitem__(self, key: str):
+        warn_deprecated(
+            '4.1.0',
+            (
+                'VersionsConnectorComponent getVersionByName, '
+                'getBuildByNumber, getPrevSuccessfulBuild, '
+                'getBuildsForChange, getBuilds, '
+                '_getRecentBuilds, and _getBuild '
+                'no longer return Build as dictionnaries. '
+                'Usage of [] accessor is deprecated: please access the member 
directly'
+            ),
+        )
+
+        if hasattr(self, key):
+            return getattr(self, key)
+
+        raise KeyError(key)
+
+def _db2data_ProjectsBuilds(model: ProjectsBuildsModel):
+    if model is None:
+        return None
+    return {
+        'id' : model.id,
+        'build_id' : model.build_id,
+        'project_uuid' : model.project_uuid,
+        'version_uuid' : model.version_uuid,
+        'buildbot_build_id' : model.buildbot_build_id,
+        'bug_id' : model.bug_id,
+        'status' : model.status,
+        'requested' : model.requested,
+        'created_at' : model.created_at,
+        'updated_at' : model.updated_at,
+        'deleted' : model.deleted,
+        'deleted_at' : model.deleted_at
+    }
 
 class BuildsConnectorComponent(base.DBConnectorComponent):
 
-    #@defer.inlineCallbacks
     def addBuild(self, project_build_data):
-        created_at = int(self.master.reactor.seconds())
-        def thd(conn, no_recurse=False):
-            tbl = self.db.model.projects_builds
+        def thd(conn):
             # get the highest current number
-            r = conn.execute(sa.select([sa.func.max(tbl.c.build_id)],
-                                       whereclause=(tbl.c.project_uuid == 
project_build_data['project_uuid'])))
+            tbl = self.db.model.projects_builds
+            r = conn.execute(
+                
sa.select(sa.func.max(tbl.c.build_id)).where(tbl.c.project_uuid == 
project_build_data['project_uuid'])
+            )
             number = r.scalar()
             new_number = 1 if number is None else number + 1
+            insert_row = {
+                'project_uuid' : project_build_data['project_uuid'],
+                'version_uuid' : project_build_data['version_uuid'],
+                'status' : project_build_data['status'],
+                'requested' : project_build_data['requested'],
+                'created_at' : int(self.master.reactor.seconds()),
+                'buildbot_build_id' : 0,
+                'build_id' : new_number,
+                'bug_id' : 0,
+            }
             try:
-                q = tbl.insert()
-                r = conn.execute(q, 
dict(project_uuid=project_build_data['project_uuid'],
-                                         
version_uuid=project_build_data['version_uuid'],
-                                         status=project_build_data['status'],
-                                         
requested=project_build_data['requested'],
-                                         created_at=created_at,
-                                         buildbot_build_id=0,
-                                         build_id=new_number,
-                                         bug_id=0
-                                         ))
+                r = conn.execute(tbl.insert(), insert_row)
+                conn.commit()
             except (sa.exc.IntegrityError, sa.exc.ProgrammingError):
-                id = None
-                new_number = None
-            else:
-                id = r.inserted_primary_key[0]
-            return id, new_number
+                conn.rollback()
+                return None, None
+            return r.inserted_primary_key[0], new_number
         return self.db.pool.do(thd)
 
-    @defer.inlineCallbacks
     def setStatusBuilds(self, id, status):
-        updated_at = int(self.master.reactor.seconds())
-        def thd(conn, no_recurse=False):
-                tbl = self.db.model.projects_builds
-                q = tbl.update()
-                q = q.where(tbl.c.id == id)
-                conn.execute(q, updated_at=updated_at,
-                                status=status)
-        yield self.db.pool.do(thd)
-
-    @defer.inlineCallbacks
+        def thd(conn):
+            tbl = self.db.model.projects_builds
+            q = tbl.update().where(tbl.c.id == id)
+            
conn.execute(q.values(updated_at=int(self.master.reactor.seconds()), 
status=status))
+        return self.db.pool.do(thd)
+
     def setBuildbotBuildIdBuilds(self, id, buildbot_build_id):
-        updated_at = int(self.master.reactor.seconds())
-        def thd(conn, no_recurse=False):
-                tbl = self.db.model.projects_builds
-                q = tbl.update()
-                q = q.where(tbl.c.id == id)
-                conn.execute(q, updated_at=updated_at,
-                                buildbot_build_id=buildbot_build_id)
-        yield self.db.pool.do(thd)
-
-    @defer.inlineCallbacks
+        def thd(conn):
+            tbl = self.db.model.projects_builds
+            q = tbl.update().where(tbl.c.id == id)
+            
conn.execute(q.values(updated_at=int(self.master.reactor.seconds()), 
buildbot_build_id=buildbot_build_id))
+        return self.db.pool.do(thd)
+
     def setBugIdBuilds(self, id, bug_id):
-        updated_at = int(self.master.reactor.seconds())
-        def thd(conn, no_recurse=False):
-                tbl = self.db.model.projects_builds
-                q = tbl.update()
-                q = q.where(tbl.c.id == id)
-                conn.execute(q, updated_at=updated_at, bug_id=bug_id)
-        yield self.db.pool.do(thd)
-
-    @defer.inlineCallbacks
-    def getBuildsByVersionUuid(self, uuid):
         def thd(conn):
+            tbl = self.db.model.projects_builds
+            q = tbl.update().where(tbl.c.id == id)
+            
conn.execute(q.values(updated_at=int(self.master.reactor.seconds()), 
bug_id=bug_id))
+        return self.db.pool.do(thd)
+
+    def getBuildsByVersionUuid(self, uuid) -> 
defer.Deferred[list[ProjectsBuildsModel]]:
+        def thd(conn) -> list[ProjectsBuildsModel]:
             tbl = self.db.model.projects_builds
             q = tbl.select()
             q = q.where(tbl.c.version_uuid == uuid)
             res = conn.execute(q)
-            row = res.fetchone()
-            return [self._row2dict(conn, row)
-                for row in conn.execute(q).fetchall()]
-        res = yield self.db.pool.do(thd)
-        return res
-
-    @defer.inlineCallbacks
-    def removeBuild(self, id):
-        def thd(conn, no_recurse=False):
-                tbl = self.db.model.projects_builds
-                q = tbl.delete()
-                q = q.where(tbl.c.id == id)
-                conn.execute(q)
-        yield self.db.pool.do(thd)
-
-    def _row2dict(self, conn, row):
-        return dict(
+            return list(self._model_from_row(row) for row in res.fetchall())
+        return self.db.pool.do(thd)
+
+    def removeBuild(self, id: int) -> defer.Deferred[None]:
+        def thd(conn) -> None:
+            tbl = self.db.model.projects_builds
+            q = tbl.delete().where(tbl.c.id == id)
+            res = conn.execute(q)
+            conn.commit()
+            res.close()
+        return self.db.pool.do(thd)
+
+    def _model_from_row(self, row):
+        return ProjectsBuildsModel(
             id=row.id,
             build_id=row.build_id,
             project_uuid=row.project_uuid,

diff --git a/buildbot_gentoo_ci/db/connector.py 
b/buildbot_gentoo_ci/db/connector.py
index 0cc7884..65d74fc 100644
--- a/buildbot_gentoo_ci/db/connector.py
+++ b/buildbot_gentoo_ci/db/connector.py
@@ -104,10 +104,8 @@ class DBConnector(service.ReconfigurableServiceMixin,
         log.msg(f"Setting up database with URL 
{repr(util.stripUrlPassword(db_url))}")
 
         # set up the engine and pool
-        self._engine = enginestrategy.create_engine(db_url,
-                                                    basedir=self.basedir)
-        self.pool = pool.DBThreadPool(
-            self._engine, reactor=self.master.reactor, verbose=verbose)
+        self._engine = enginestrategy.create_engine(db_url, 
basedir=self.basedir)
+        self.pool = pool.DBThreadPool(self._engine, 
reactor=self.master.reactor, verbose=verbose)
 
         # make sure the db is up to date, unless specifically asked not to
         if check_version:

diff --git a/buildbot_gentoo_ci/db/model.py b/buildbot_gentoo_ci/db/model.py
index 448e67f..d5364c7 100644
--- a/buildbot_gentoo_ci/db/model.py
+++ b/buildbot_gentoo_ci/db/model.py
@@ -17,8 +17,11 @@
 # Modifyed by Gentoo Authors.
 # Copyright 2024 Gentoo Authors
 
-import uuid
+from __future__ import annotations
+
+from typing import TYPE_CHECKING
 
+import uuid
 import alembic
 import alembic.config
 import sqlalchemy as sa
@@ -32,26 +35,9 @@ from buildbot.db.migrate_utils import test_unicode
 from buildbot.db.types.json import JsonObject
 from buildbot.util import sautils
 
-
-class UpgradeFromBefore0p9Error(Exception):
-
-    def __init__(self):
-        message = """You are trying to upgrade a buildbot 0.8.x master to 
buildbot 0.9.x or newer.
-        This is not supported. Please start from a clean database
-        http://docs.buildbot.net/latest/manual/upgrading/0.9-upgrade.html""";
-        # Call the base class constructor with the parameters it needs
-        super().__init__(message)
-
-
-class UpgradeFromBefore3p0Error(Exception):
-
-    def __init__(self):
-        message = """You are trying to upgrade to Buildbot 3.0 or newer from 
Buildbot 2.x or older.
-        This is only supported via an intermediate upgrade to newest Buildbot 
2.10.x that is
-        available. Please first upgrade to 2.10.x and then try to upgrade to 
this version.
-        http://docs.buildbot.net/latest/manual/upgrading/3.0-upgrade.html""";
-        super().__init__(message)
-
+if TYPE_CHECKING:
+    from sqlalchemy.engine.base import Connectable as SQLAConnection
+    from sqlalchemy.engine.reflection import Inspector
 
 class Model(base.DBConnectorComponent):
 
@@ -364,6 +350,7 @@ class Model(base.DBConnectorComponent):
         sa.Column('change_id', sa.Integer, nullable=True, default=0),
         sa.Column('deleted', sa.Boolean, default=False),
         sa.Column('deleted_at', sa.Integer, nullable=True),
+        sa.Column('created_at', sa.Integer, nullable=True),
     )
 
     versions_keywords = sautils.Table(
@@ -496,13 +483,9 @@ class Model(base.DBConnectorComponent):
 
     config_path = util.sibpath(__file__, "migrations/alembic.ini")
 
-    def table_exists(self, conn, table):
-        try:
-            r = conn.execute(f"select * from {table} limit 1")
-            r.close()
-            return True
-        except Exception:
-            return False
+    def table_exists(self, conn: SQLAConnection, table: str):
+        inspector: Inspector = sa.inspect(conn.engine)
+        return inspector.has_table(table)
 
     def migrate_get_version(self, conn):
         r = conn.execute("select version from migrate_version limit 1")
@@ -550,19 +533,10 @@ class Model(base.DBConnectorComponent):
             alembic_scripts = self.alembic_get_scripts()
             current_script_rev_head = alembic_scripts.get_current_head()
 
-            #if self.table_exists(conn, 'version'):
-            #    raise UpgradeFromBefore0p9Error()
-
             if self.table_exists(conn, 'migrate_version'):
                 version = self.migrate_get_version(conn)
 
-                #if version < 40:
-                #    raise UpgradeFromBefore0p9Error()
-
-                last_sqlalchemy_migrate_version = 0
-                if version != last_sqlalchemy_migrate_version:
-                    raise UpgradeFromBefore3p0Error()
-
+                last_sqlalchemy_migrate_version = 58
                 self.alembic_stamp(conn, alembic_scripts, 
alembic_scripts.get_base())
                 conn.execute('drop table migrate_version')
 
@@ -576,6 +550,11 @@ class Model(base.DBConnectorComponent):
                 self.alembic_stamp(conn, alembic_scripts, 
current_script_rev_head)
                 return
 
+            def upgrade(rev, context):
+                log.msg(f'Upgrading from {rev} to {current_script_rev_head}')
+                return alembic_scripts._upgrade_revs(current_script_rev_head, 
rev)
+
+
             context = 
alembic.runtime.migration.MigrationContext.configure(conn)
             current_rev = context.get_current_revision()
 

diff --git a/buildbot_gentoo_ci/db/packages.py 
b/buildbot_gentoo_ci/db/packages.py
index ad4a244..2e29c02 100644
--- a/buildbot_gentoo_ci/db/packages.py
+++ b/buildbot_gentoo_ci/db/packages.py
@@ -15,7 +15,11 @@
 # Copyright Buildbot Team Members
 # Origins: buildbot.db.*
 # Modifyed by Gentoo Authors.
-# Copyright 2021 Gentoo Authors
+# Copyright 2024 Gentoo Authors
+
+from __future__ import annotations
+from dataclasses import dataclass
+from typing import TYPE_CHECKING
 
 import uuid
 import sqlalchemy as sa
@@ -23,12 +27,42 @@ import sqlalchemy as sa
 from twisted.internet import defer
 
 from buildbot.db import base
+from buildbot.warnings import warn_deprecated
+
+if TYPE_CHECKING:
+    import datetime
+
+@dataclass
+class PackageModel:
+    uuid : str
+    name : str
+    category_uuid : str
+    repository_uuid : str
+    deleted : bool
+    deleted_at : datetime.datetime | None
+
+    # For backward compatibility
+    def __getitem__(self, key: str):
+        if hasattr(self, key):
+            return getattr(self, key)
+        raise KeyError(key)
+
+def _db2data_Package(model: PackageModel):
+    if model is None:
+        return None
+    return {
+            'uuid' : model.uuid,
+            'name' : model.name,
+            'category_uuid' : model.category_uuid,
+            'repository_uuid' : model.repository_uuid,
+            'deleted' : model.deleted,
+            'deleted_at' : model.deleted_at,
+    }
 
 class PackagesConnectorComponent(base.DBConnectorComponent):
 
-    @defer.inlineCallbacks
-    def getPackageByName(self, name, c_uuid, repo_uuid, deleted=False):
-        def thd(conn):
+    def getPackageByName(self, name: str, c_uuid: str, repo_uuid: str, 
deleted: bool | None = False) -> defer.Deferred[PackageModel | None]:
+        def thd(conn) -> PackageModel | None:
             tbl = self.db.model.packages
             q = tbl.select()
             q = q.where(tbl.c.name == name)
@@ -37,52 +71,54 @@ class PackagesConnectorComponent(base.DBConnectorComponent):
             q = q.where(tbl.c.repository_uuid == repo_uuid)
             res = conn.execute(q)
             row = res.fetchone()
-            if not row:
-                return None
-            return self._row2dict(conn, row)
-        res = yield self.db.pool.do(thd)
-        return res
+            rv = None
+            if row:
+                rv = self._model_from_row_PackageModel(row)
+            res.close()
+            return rv
+        return self.db.pool.do(thd)
 
-    @defer.inlineCallbacks
-    def getPackageByUuid(self, uuid):
-        def thd(conn):
+    def getPackageByUuid(self, uuid: str) -> defer.Deferred[PackageModel | 
None]:
+        def thd(conn) -> PackageModel | None:
             tbl = self.db.model.packages
             q = tbl.select()
             q = q.where(tbl.c.uuid == uuid)
             res = conn.execute(q)
             row = res.fetchone()
-            if not row:
-                return None
-            return self._row2dict(conn, row)
-        res = yield self.db.pool.do(thd)
-        return res
+            rv = None
+            if row:
+                rv = self._model_from_row_PackageModel(row)
+            res.close()
+            return rv
+        return self.db.pool.do(thd)
 
-    @defer.inlineCallbacks
-    def addPackage(self, name, repository_uuid, category_uuid):
-        def thd(conn, no_recurse=False):
+    def addPackage(self, name: str, repository_uuid: str, category_uuid: str) 
-> defer.Deferred[str]:
+        def thd(conn) -> str:
+            insert_row = {
+                'name' : name,
+                'repository_uuid' : repository_uuid,
+                'category_uuid' : category_uuid,
+                'deleted_at' : 0,
+                'deleted' : False,
+            }
             try:
-                tbl = self.db.model.packages
-                q = tbl.insert()
-                r = conn.execute(q, dict(name=name,
-                                         repository_uuid=repository_uuid,
-                                         category_uuid=category_uuid))
-            except Exception as e:
-                print(type(e))
-                print(e.args)
-                print(e)
-                uuid = None
+                r = conn.execute(self.db.model.packages.insert(), insert_row)
+                conn.commit()
+            except (sa.exc.IntegrityError, sa.exc.ProgrammingError):
+                conn.rollback()
+                return None
             else:
-                uuid = r.inserted_primary_key[0]
-            return uuid
-        res = yield self.db.pool.do(thd)
-        return res
+                return r.inserted_primary_key[0]
+        return self.db.pool.do(thd)
 
-    def _row2dict(self, conn, row):
-        return dict(
+    def _model_from_row_PackageModel(self, row):
+        return PackageModel(
             uuid=row.uuid,
             name=row.name,
             repository_uuid=row.repository_uuid,
-            category_uuid=row.category_uuid
+            category_uuid=row.category_uuid,
+            deleted=row.deleted,
+            deleted_at=row.deleted_at,
             )
 
     @defer.inlineCallbacks
@@ -209,8 +245,7 @@ class PackagesConnectorComponent(base.DBConnectorComponent):
     def delPackageEmail(self, package_uuid):
         def thd(conn, no_recurse=False):
             tbl = self.db.model.packages_emails
-            conn.execute(tbl.delete(
-                whereclause=((tbl.c.package_uuid == package_uuid))))
+            conn.execute(tbl.delete().where(tbl.c.package_uuid == 
package_uuid))
         res = yield self.db.pool.do(thd)
         return res
 

diff --git a/buildbot_gentoo_ci/db/versions.py 
b/buildbot_gentoo_ci/db/versions.py
index afb9e52..60946c5 100644
--- a/buildbot_gentoo_ci/db/versions.py
+++ b/buildbot_gentoo_ci/db/versions.py
@@ -15,7 +15,11 @@
 # Copyright Buildbot Team Members
 # Origins: buildbot.db.*
 # Modifyed by Gentoo Authors.
-# Copyright 2021 Gentoo Authors
+# Copyright 2024 Gentoo Authors
+
+from __future__ import annotations
+from dataclasses import dataclass
+from typing import TYPE_CHECKING
 
 import uuid
 import sqlalchemy as sa
@@ -23,11 +27,48 @@ import sqlalchemy as sa
 from twisted.internet import defer
 
 from buildbot.db import base
+from buildbot.warnings import warn_deprecated
+
+if TYPE_CHECKING:
+    import datetime
+
+@dataclass
+class VersionModel:
+    uuid: str
+    name: str
+    package_uuid: str
+    file_hash: str
+    commit_id: str
+    change_id: int
+    created_at: datetime.datetime | None
+    deleted: bool
+    deleted_at: datetime.datetime | None
+
+    # For backward compatibility
+    def __getitem__(self, key: str):
+        if hasattr(self, key):
+            return getattr(self, key)
+        raise KeyError(key)
+
+def _db2data_Version(model: VersionModel):
+    if model is None:
+        return None
+    return {
+            'uuid' : model.uuid,
+            'name' : model.name,
+            'package_uuid' : model.package_uuid,
+            'file_hash' : model.file_hash,
+            'commit_id' : model.commit_id,
+            'change_id' : model.change_id,
+            'deleted' : model.deleted,
+            'deleted_at' : model.deleted_at,
+            'created_at' : model.created_at,
+    }
+
 class VersionsConnectorComponent(base.DBConnectorComponent):
 
-    @defer.inlineCallbacks
-    def getVersionByName(self, name, p_uuid, deleted=False):
-        def thd(conn):
+    def getVersionByName(self, name: str, p_uuid: str, deleted: bool | None = 
False) -> defer.Deferred[VersionModel | None]:
+        def thd(conn) -> VersionModel | None:
             tbl = self.db.model.versions
             q = tbl.select()
             q = q.where(tbl.c.name == name)
@@ -35,56 +76,57 @@ class VersionsConnectorComponent(base.DBConnectorComponent):
             q = q.where(tbl.c.deleted == deleted)
             res = conn.execute(q)
             row = res.fetchone()
-            if not row:
-                return None
-            return self._row2dict(conn, row)
-        res = yield self.db.pool.do(thd)
-        return res
-
-    @defer.inlineCallbacks
-    def getVersionByUuid(self, uuid):
-        def thd(conn):
+            rv = None
+            if row:
+                rv = self._model_from_row_VersionModel(row)
+            res.close()
+            return rv
+        return self.db.pool.do(thd)
+
+    def getVersionByUuid(self, uuid: str) -> defer.Deferred[VersionModel | 
None]:
+        def thd(conn) -> VersionModel | None:
             tbl = self.db.model.versions
             q = tbl.select()
             q = q.where(tbl.c.uuid == uuid)
             res = conn.execute(q)
             row = res.fetchone()
-            if not row:
-                return None
-            return self._row2dict(conn, row)
-        res = yield self.db.pool.do(thd)
-        return res
-
-    @defer.inlineCallbacks
-    def addVersion(self, name, package_uuid, file_hash, commit_id, change_id):
-        def thd(conn, no_recurse=False):
+            rv = None
+            if row:
+                rv = self._model_from_row_VersionModel(row)
+            res.close()
+            return rv
+        return self.db.pool.do(thd)
+
+    def addVersion(self, name: str, package_uuid: str, file_hash: str, 
commit_id: int, change_id: int) -> defer.Deferred[str]:
+        def thd(conn) -> str:
+            insert_row = {
+                'name': name,
+                'package_uuid' : package_uuid,
+                'file_hash' : file_hash,
+                'commit_id' : commit_id,
+                'change_id' : change_id,
+                'created_at' : int(self.master.reactor.seconds()),
+                'deleted_at' : 0,
+                'deleted' : False,
+            }
             try:
-                tbl = self.db.model.versions
-                q = tbl.insert()
-                r = conn.execute(q, dict(name=name,
-                                         package_uuid=package_uuid,
-                                         file_hash=file_hash,
-                                         commit_id=commit_id,
-                                         change_id=change_id))
+                r = conn.execute(self.db.model.versions.insert(), insert_row)
+                conn.commit()
             except (sa.exc.IntegrityError, sa.exc.ProgrammingError):
-                uuid = None
+                conn.rollback()
+                return None
             else:
-                uuid = r.inserted_primary_key[0]
-            return uuid
-        res = yield self.db.pool.do(thd)
-        return res
+                return r.inserted_primary_key[0]
+        return self.db.pool.do(thd)
 
-    @defer.inlineCallbacks
     def delVersion(self, uuid):
-        deleted_at = int(self.master.reactor.seconds())
-        def thd(conn, no_recurse=False):
-        
-                tbl = self.db.model.versions
-                q = tbl.update()
-                q = q.where(tbl.c.uuid == uuid)
-                conn.execute(q, deleted=True,
-                                deleted_at=deleted_at)
-        yield self.db.pool.do(thd)
+        def thd(conn):
+            tbl = self.db.model.versions
+            q = tbl.update().where(tbl.c.uuid == uuid)
+            res = conn.execute(q.values(deleted=True, 
deleted_at=int(self.master.reactor.seconds())))
+            #conn.commit()
+            res.close()
+        return self.db.pool.do(thd)
 
     @defer.inlineCallbacks
     def addKeyword(self, version_uuid, keyword_id, status):
@@ -95,6 +137,7 @@ class VersionsConnectorComponent(base.DBConnectorComponent):
                 r = conn.execute(q, dict(version_uuid=version_uuid,
                                          keyword_id=keyword_id,
                                          status=status))
+                conn.commit()
             except (sa.exc.IntegrityError, sa.exc.ProgrammingError):
                 uuid = None
             else:
@@ -112,6 +155,7 @@ class VersionsConnectorComponent(base.DBConnectorComponent):
                 r = conn.execute(q, dict(version_uuid=version_uuid,
                                          metadata=metadata,
                                          value=value))
+                #conn.commit()
             except (sa.exc.IntegrityError, sa.exc.ProgrammingError):
                 id = None
             else:
@@ -140,41 +184,44 @@ class 
VersionsConnectorComponent(base.DBConnectorComponent):
             q = tbl.select()
             q = q.where(tbl.c.deleted == deleted)
             q = q.where(tbl.c.package_uuid == p_uuid)
-            return [self._row2dict(conn, row)
+            return [self._model_from_row_VersionModel(row)
                 for row in conn.execute(q).fetchall()]
         res = yield self.db.pool.do(thd)
         return res
 
-    @defer.inlineCallbacks
-    def removeVersion(self, uuid):
-        def thd(conn, no_recurse=False):
+    def removeVersion(self, uuid: str) -> defer.Deferred[None]:
+        def thd(conn) -> None:
                 tbl = self.db.model.versions
                 q = tbl.delete()
                 q = q.where(tbl.c.uuid == uuid)
-                conn.execute(q)
-        yield self.db.pool.do(thd)
+                res = conn.execute(q)
+                conn.commit()
+                res.close()
+        return self.db.pool.do(thd)
 
-    @defer.inlineCallbacks
-    def removeVersionMetadata(self, version_uuid):
-        def thd(conn, no_recurse=False):
+    def removeVersionMetadata(self, version_uuid: str) -> defer.Deferred[None]:
+        def thd(conn) -> None:
                 tbl = self.db.model.versions_metadata
                 q = tbl.delete()
                 q = q.where(tbl.c.version_uuid == version_uuid)
-                conn.execute(q)
-        yield self.db.pool.do(thd)
+                res = conn.execute(q)
+                conn.commit()
+                res.close()
+        return self.db.pool.do(thd)
 
-    @defer.inlineCallbacks
-    def removeVersionKeyword(self, version_uuid):
-        def thd(conn, no_recurse=False):
+    def removeVersionKeyword(self, version_uuid: str) -> defer.Deferred[None]:
+        def thd(conn) -> None:
                 tbl = self.db.model.versions_keywords
                 q = tbl.delete()
                 q = q.where(tbl.c.version_uuid == version_uuid)
-                conn.execute(q)
-        yield self.db.pool.do(thd)
+                res = conn.execute(q)
+                conn.commit()
+                res.close()
+        return self.db.pool.do(thd)
 
 
-    def _row2dict(self, conn, row):
-        return dict(
+    def _model_from_row_VersionModel(self, row):
+        return VersionModel(
             uuid=row.uuid,
             name=row.name,
             package_uuid=row.package_uuid,
@@ -182,7 +229,8 @@ class VersionsConnectorComponent(base.DBConnectorComponent):
             commit_id=row.commit_id,
             change_id = row.change_id,
             deleted=row.deleted,
-            deleted_at=row.deleted_at
+            deleted_at=row.deleted_at,
+            created_at=row.created_at,
             )
 
     def _row2dict_version_metadata(self, conn, row):

Reply via email to