# SPDX-License-Identifier: GPL-3.0-or-later # Haketilo proxy data and configuration (MappingRef and MappingStore subtypes). # # This file is part of Hydrilla&Haketilo. # # Copyright (C) 2022 Wojtek Kosior # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # # I, Wojtek Kosior, thereby promise not to sue for violation of this # file's license. Although I request that you do not make use this code # in a proprietary program, I am not going to enforce this in court. """ This module provides an interface to interact with mappings inside Haketilo. """ # Enable using with Python 3.7. from __future__ import annotations import io import typing as t import dataclasses as dc from ... import item_infos from .. import state as st from . import base @dc.dataclass(frozen=True, unsafe_hash=True) class ConcreteMappingRef(st.MappingRef): state: base.HaketiloStateWithFields = dc.field(hash=False, compare=False) def get_version_display_infos(self) \ -> t.Sequence[st.MappingVersionDisplayInfo]: with self.state.cursor() as cursor: cursor.execute( ''' SELECT item_version_id, definition, repo, repo_iteration, installed, is_active, is_orphan, is_local, enabled FROM mapping_display_infos WHERE item_id = ?; ''', (self.id,) ) rows = cursor.fetchall() if rows == []: raise st.MissingItemError() result = [] for (item_version_id, definition, repo, repo_iteration, installed, is_active, is_orphan, is_local, status_letter) in rows: ref = ConcreteMappingVersionRef(str(item_version_id), self.state) item_info = item_infos.MappingInfo.load( definition, repo, repo_iteration ) display_info = st.MappingVersionDisplayInfo( ref = ref, info = item_info, installed = st.InstalledStatus(installed), is_active = is_active, is_orphan = is_orphan, is_local = is_local, mapping_enabled = st.EnabledStatus(status_letter) ) result.append(display_info) return sorted(result, key=(lambda di: di.info)) @dc.dataclass(frozen=True) class ConcreteMappingStore(st.MappingStore): state: base.HaketiloStateWithFields def get(self, id: str) -> st.MappingRef: return ConcreteMappingRef(id, self.state) def get_display_infos(self) -> t.Sequence[st.MappingDisplayInfo]: with self.state.cursor() as cursor: cursor.execute( ''' SELECT DISTINCT item_id, identifier, CASE WHEN enabled IN ('A', 'E') THEN item_version_id ELSE NULL END, CASE WHEN enabled IN ('A', 'E') THEN definition ELSE NULL END, CASE WHEN enabled IN ('A', 'E') THEN repo ELSE NULL END, CASE WHEN enabled IN ('A', 'E') THEN repo_iteration ELSE NULL END, enabled FROM mapping_display_infos WHERE is_active OR item_version_id IS NULL; ''' ) rows = cursor.fetchall() result = [] for (item_id, identifier, item_version_id, definition, repo, repo_iteration, status_letter) in rows: ref = ConcreteMappingRef(str(item_id), self.state) version_ref: t.Optional[st.MappingVersionRef] = None item_info: t.Optional[item_infos.MappingInfo] = None if item_version_id is not None: active_version_ref = ConcreteMappingVersionRef( id = str(item_version_id), state = self.state ) item_info = item_infos.MappingInfo.load( definition, repo, repo_iteration ) display_info = st.MappingDisplayInfo( ref = ref, identifier = identifier, enabled = st.EnabledStatus(status_letter), active_version_ref = active_version_ref, active_version_info = item_info ) result.append(display_info) return result @dc.dataclass(frozen=True, unsafe_hash=True) class ConcreteMappingVersionRef(st.MappingVersionRef): state: base.HaketiloStateWithFields = dc.field(hash=False, compare=False) def update_status(self, new_status: st.EnabledStatus) -> None: """....""" assert new_status != st.EnabledStatus.AUTO_ENABLED raise NotImplementedError() def get_display_info(self) -> st.MappingVersionDisplayInfo: with self.state.cursor() as cursor: cursor.execute( ''' SELECT definition, repo, repo_iteration, installed, is_orphan, is_active, is_local, enabled FROM mapping_display_infos WHERE item_version_id = ?; ''', (self.id,) ) rows = cursor.fetchall() if rows == []: raise st.MissingItemError() (definition, repo, repo_iteration, installed, is_orphan, is_active, is_local, status_letter), = rows item_info = item_infos.MappingInfo.load( definition, repo, repo_iteration ) return st.MappingVersionDisplayInfo( ref = self, info = item_info, installed = st.InstalledStatus(installed), is_active = is_active, is_orphan = is_orphan, is_local = is_local, mapping_enabled = st.EnabledStatus(status_letter) ) @dc.dataclass(frozen=True) class ConcreteMappingVersionStore(st.MappingVersionStore): state: base.HaketiloStateWithFields def get(self, id: str) -> st.MappingVersionRef: return ConcreteMappingVersionRef(id, self.state)