home · contact · privacy
Enable deletion of Conditions.
[plomtask] / plomtask / processes.py
index 590c5bca56d3f84c1b67f34ee3f80c084903b1c9..e67b13414e26d40a87e77545ce57d238bc050028 100644 (file)
@@ -1,7 +1,8 @@
 """Collecting Processes and Process-related items."""
 from __future__ import annotations
 from dataclasses import dataclass
 """Collecting Processes and Process-related items."""
 from __future__ import annotations
 from dataclasses import dataclass
-from typing import Set
+from typing import Set, Any
+from sqlite3 import Row
 from plomtask.db import DatabaseConnection, BaseModel
 from plomtask.misc import VersionedAttribute
 from plomtask.conditions import Condition, ConditionsRelations
 from plomtask.db import DatabaseConnection, BaseModel
 from plomtask.misc import VersionedAttribute
 from plomtask.conditions import Condition, ConditionsRelations
@@ -25,7 +26,7 @@ class Process(BaseModel[int], ConditionsRelations):
     # pylint: disable=too-many-instance-attributes
 
     def __init__(self, id_: int | None) -> None:
     # pylint: disable=too-many-instance-attributes
 
     def __init__(self, id_: int | None) -> None:
-        self.set_int_id(id_)
+        super().__init__(id_)
         self.title = VersionedAttribute(self, 'process_titles', 'UNNAMED')
         self.description = VersionedAttribute(self, 'process_descriptions', '')
         self.effort = VersionedAttribute(self, 'process_efforts', 1.0)
         self.title = VersionedAttribute(self, 'process_titles', 'UNNAMED')
         self.description = VersionedAttribute(self, 'process_descriptions', '')
         self.effort = VersionedAttribute(self, 'process_efforts', 1.0)
@@ -35,48 +36,26 @@ class Process(BaseModel[int], ConditionsRelations):
         self.disables: list[Condition] = []
 
     @classmethod
         self.disables: list[Condition] = []
 
     @classmethod
-    def all(cls, db_conn: DatabaseConnection) -> list[Process]:
-        """Collect all Processes and their connected VersionedAttributes."""
-        processes = {}
-        for id_, process in cls.cache_.items():
-            processes[id_] = process
-        already_recorded = processes.keys()
-        for id_ in db_conn.column_all('processes', 'id'):
-            if id_ not in already_recorded:
-                process = cls.by_id(db_conn, id_)
-                assert isinstance(process.id_, int)
-                processes[process.id_] = process
-        return list(processes.values())
-
-    @classmethod
-    def by_id(cls, db_conn: DatabaseConnection, id_: int | None,
-              create: bool = False) -> Process:
-        """Collect Process, its VersionedAttributes, and its child IDs."""
-        process = None
-        from_cache = False
-        if id_:
-            process, from_cache = super()._by_id(db_conn, id_)
-        if not from_cache:
-            if not process:
-                if not create:
-                    raise NotFoundException(f'Process not found of id: {id_}')
-                process = Process(id_)
-            if isinstance(process.id_, int):
-                for name in ('title', 'description', 'effort'):
-                    table = f'process_{name}s'
-                    for row in db_conn.row_where(table, 'parent', process.id_):
-                        getattr(process, name).history_from_row(row)
-                for row in db_conn.row_where('process_steps', 'owner',
-                                             process.id_):
-                    step = ProcessStep.from_table_row(db_conn, row)
-                    process.explicit_steps += [step]
-                for name in ('conditions', 'enables', 'disables'):
-                    table = f'process_{name}'
-                    for c_id in db_conn.column_where(table, 'condition',
-                                                     'process', process.id_):
-                        target = getattr(process, name)
-                        target += [Condition.by_id(db_conn, c_id)]
-        assert isinstance(process, Process)
+    def from_table_row(cls, db_conn: DatabaseConnection,
+                       row: Row | list[Any]) -> Process:
+        """Make from DB row, with dependencies."""
+        process = super().from_table_row(db_conn, row)
+        assert isinstance(process.id_, int)
+        for name in ('title', 'description', 'effort'):
+            table = f'process_{name}s'
+            for row_ in db_conn.row_where(table, 'parent', process.id_):
+                getattr(process, name).history_from_row(row_)
+        for row_ in db_conn.row_where('process_steps', 'owner',
+                                      process.id_):
+            step = ProcessStep.from_table_row(db_conn, row_)
+            process.explicit_steps += [step]  # pylint: disable=no-member
+        for name in ('conditions', 'enables', 'disables'):
+            table = f'process_{name}'
+            assert isinstance(process.id_, int)
+            for c_id in db_conn.column_where(table, 'condition',
+                                             'process', process.id_):
+                target = getattr(process, name)
+                target += [Condition.by_id(db_conn, c_id)]
         return process
 
     def used_as_step_by(self, db_conn: DatabaseConnection) -> list[Process]:
         return process
 
     def used_as_step_by(self, db_conn: DatabaseConnection) -> list[Process]:
@@ -190,6 +169,16 @@ class Process(BaseModel[int], ConditionsRelations):
         for step in self.explicit_steps:
             step.save(db_conn)
 
         for step in self.explicit_steps:
             step.save(db_conn)
 
+    def remove(self, db_conn: DatabaseConnection) -> None:
+        """Remove from DB, with dependencies."""
+        assert isinstance(self.id_, int)
+        db_conn.delete_where('process_conditions', 'process', self.id_)
+        db_conn.delete_where('process_enables', 'process', self.id_)
+        db_conn.delete_where('process_disables', 'process', self.id_)
+        for step in self.explicit_steps:
+            step.remove(db_conn)
+        super().remove(db_conn)
+
 
 class ProcessStep(BaseModel[int]):
     """Sub-unit of Processes."""
 
 class ProcessStep(BaseModel[int]):
     """Sub-unit of Processes."""
@@ -198,20 +187,17 @@ class ProcessStep(BaseModel[int]):
 
     def __init__(self, id_: int | None, owner_id: int, step_process_id: int,
                  parent_step_id: int | None) -> None:
 
     def __init__(self, id_: int | None, owner_id: int, step_process_id: int,
                  parent_step_id: int | None) -> None:
-        self.set_int_id(id_)
+        super().__init__(id_)
         self.owner_id = owner_id
         self.step_process_id = step_process_id
         self.parent_step_id = parent_step_id
 
         self.owner_id = owner_id
         self.step_process_id = step_process_id
         self.parent_step_id = parent_step_id
 
-    @classmethod
-    def by_id(cls, db_conn: DatabaseConnection, id_: int) -> ProcessStep:
-        """Retrieve ProcessStep by id_, or throw NotFoundException."""
-        step, _ = super()._by_id(db_conn, id_)
-        if step:
-            assert isinstance(step, ProcessStep)
-            return step
-        raise NotFoundException(f'found no ProcessStep of ID {id_}')
-
     def save(self, db_conn: DatabaseConnection) -> None:
         """Default to simply calling self.save_core for simple cases."""
         self.save_core(db_conn)
     def save(self, db_conn: DatabaseConnection) -> None:
         """Default to simply calling self.save_core for simple cases."""
         self.save_core(db_conn)
+
+    def remove(self, db_conn: DatabaseConnection) -> None:
+        """Remove from DB, and owner's .explicit_steps."""
+        owner = Process.by_id(db_conn, self.owner_id)
+        owner.explicit_steps.remove(self)
+        super().remove(db_conn)