# SPDX-License-Identifier: GPL-3.0-or-later # Haketilo proxy data and configuration (RepoRef and RepoStore 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 repositories configured inside Haketilo. """ # Enable using with Python 3.7. from __future__ import annotations import typing as t import dataclasses as dc from datetime import datetime from .. import state as st from . import base def make_repo_display_info( ref: st.RepoRef, name: str, url: t.Optional[str], deleted: t.Optional[bool], last_refreshed: t.Optional[int], resource_count: int, mapping_count: int ) -> st.RepoDisplayInfo: last_refreshed_converted: t.Optional[datetime] = None if last_refreshed is not None: last_refreshed_converted = datetime.fromtimestamp(last_refreshed) return st.RepoDisplayInfo( ref = ref, name = name, url = url, deleted = deleted, last_refreshed = last_refreshed_converted, resource_count = resource_count, mapping_count = mapping_count ) @dc.dataclass(frozen=True, unsafe_hash=True) class ConcreteRepoRef(st.RepoRef): """....""" state: base.HaketiloStateWithFields = dc.field(hash=False, compare=False) def remove(self) -> None: raise NotImplementedError() def update( self, *, name: t.Optional[str] = None, url: t.Optional[str] = None ) -> st.RepoRef: raise NotImplementedError() def refresh(self) -> st.RepoIterationRef: raise NotImplementedError() def get_display_info(self) -> st.RepoDisplayInfo: with self.state.cursor() as cursor: cursor.execute( ''' SELECT name, url, deleted, last_refreshed, resource_count, mapping_count FROM repo_display_infos WHERE repo_id = ?; ''', (self.id,) ) rows = cursor.fetchall() if rows == []: raise st.MissingItemError() row, = rows return make_repo_display_info(self, *row) @dc.dataclass(frozen=True) class ConcreteRepoStore(st.RepoStore): state: base.HaketiloStateWithFields def get(self, id: str) -> st.RepoRef: return ConcreteRepoRef(id, self.state) def get_display_infos(self, include_deleted: bool = False) \ -> t.Iterable[st.RepoDisplayInfo]: with self.state.cursor() as cursor: condition: str = 'TRUE' if include_deleted: condition = 'COALESCE(deleted = FALSE, TRUE)' cursor.execute( f''' SELECT repo_id, name, url, deleted, last_refreshed, resource_count, mapping_count FROM repo_display_infos WHERE {condition} ORDER BY repo_id != 1, name; ''' ) all_rows = cursor.fetchall() assert len(all_rows) > 0 and all_rows[0][0] == 1 result = [] for row in all_rows: repo_id, *rest = row ref = ConcreteRepoRef(str(repo_id), self.state) result.append(make_repo_display_info(ref, *rest)) return result