aboutsummaryrefslogtreecommitdiff
path: root/src/hydrilla/proxy/state_impl
diff options
context:
space:
mode:
authorWojtek Kosior <koszko@koszko.org>2022-08-18 13:40:16 +0200
committerWojtek Kosior <koszko@koszko.org>2022-09-28 12:54:22 +0200
commit2579081df2a568192887d776a6965af323b7c4ee (patch)
tree12491e0ee11568a09891f4d261e9cba60e8a8d52 /src/hydrilla/proxy/state_impl
parentc242a5833d41fdcee6e2b35cff7af8d445b44946 (diff)
downloadhaketilo-hydrilla-2579081df2a568192887d776a6965af323b7c4ee.tar.gz
haketilo-hydrilla-2579081df2a568192887d776a6965af323b7c4ee.zip
make it possible to list all repositories in the web UI
Diffstat (limited to 'src/hydrilla/proxy/state_impl')
-rw-r--r--src/hydrilla/proxy/state_impl/concrete_state.py22
-rw-r--r--src/hydrilla/proxy/state_impl/mappings.py2
-rw-r--r--src/hydrilla/proxy/state_impl/repos.py151
3 files changed, 155 insertions, 20 deletions
diff --git a/src/hydrilla/proxy/state_impl/concrete_state.py b/src/hydrilla/proxy/state_impl/concrete_state.py
index b2b1033..46e7827 100644
--- a/src/hydrilla/proxy/state_impl/concrete_state.py
+++ b/src/hydrilla/proxy/state_impl/concrete_state.py
@@ -52,28 +52,12 @@ from .. import state as st
from .. import policies
from . import base
from . import mappings
+from . import repos
from .load_packages import load_packages
here = Path(__file__).resolve().parent
-@dc.dataclass(frozen=True, unsafe_hash=True) # type: ignore[misc]
-class ConcreteRepoRef(st.RepoRef):
- def remove(self, state: st.HaketiloState) -> None:
- raise NotImplementedError()
-
- def update(
- self,
- state: st.HaketiloState,
- *,
- name: t.Optional[str] = None,
- url: t.Optional[str] = None
- ) -> ConcreteRepoRef:
- raise NotImplementedError()
-
- def refresh(self, state: st.HaketiloState) -> ConcreteRepoIterationRef:
- raise NotImplementedError()
-
@dc.dataclass(frozen=True, unsafe_hash=True)
class ConcreteRepoIterationRef(st.RepoIterationRef):
@@ -440,8 +424,8 @@ class ConcreteHaketiloState(base.HaketiloStateWithFields):
self.policy_tree = new_policy_tree
self.payloads_data = new_payloads_data
- def get_repo(self, repo_id: str) -> st.RepoRef:
- return ConcreteRepoRef(repo_id)
+ def repo_store(self) -> st.RepoStore:
+ return repos.ConcreteRepoStore(self)
def get_repo_iteration(self, repo_iteration_id: str) -> st.RepoIterationRef:
return ConcreteRepoIterationRef(repo_iteration_id)
diff --git a/src/hydrilla/proxy/state_impl/mappings.py b/src/hydrilla/proxy/state_impl/mappings.py
index 5e31814..3668784 100644
--- a/src/hydrilla/proxy/state_impl/mappings.py
+++ b/src/hydrilla/proxy/state_impl/mappings.py
@@ -130,4 +130,4 @@ class ConcreteMappingVersionStore(st.MappingVersionStore):
info = st.MappingDisplayInfo(ref, item_info, status, is_orphan)
result.append(info)
- return result
+ return sorted(result, key=(lambda di: di.info))
diff --git a/src/hydrilla/proxy/state_impl/repos.py b/src/hydrilla/proxy/state_impl/repos.py
new file mode 100644
index 0000000..be11a88
--- /dev/null
+++ b/src/hydrilla/proxy/state_impl/repos.py
@@ -0,0 +1,151 @@
+# 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 <https://www.gnu.org/licenses/>.
+#
+#
+# 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