From 2ee05f748c3750bbe32023bc9ee8c92e8d63b028 Mon Sep 17 00:00:00 2001 From: Moul <moul@moul.re> Date: Mon, 7 Apr 2025 11:53:51 +0200 Subject: [PATCH] Implement AccountStorage class (#477) Define tools.click_fail() (#501) --- silkaj/account_storage.py | 54 ++++++++++++++++++++++++++++++ silkaj/tools.py | 5 +++ tests/unit/test_account_storage.py | 49 +++++++++++++++++++++++++++ 3 files changed, 108 insertions(+) create mode 100644 silkaj/account_storage.py create mode 100644 tests/unit/test_account_storage.py diff --git a/silkaj/account_storage.py b/silkaj/account_storage.py new file mode 100644 index 00000000..f955af7e --- /dev/null +++ b/silkaj/account_storage.py @@ -0,0 +1,54 @@ +# Copyright 2016-2025 Maël Azimi <m.a@moul.re> +# +# Silkaj is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Silkaj 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 Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Silkaj. If not, see <https://www.gnu.org/licenses/>. + +from pathlib import Path + +from silkaj import tools +from silkaj.blockchain import tools as bc_tools + + +class AccountStorage: + xdg_data_home = ".local/share" + program_name = "silkaj" + revocation_file_name = "revocation.txt" + authentication_v1_file_name = "authentication_file_ed25519.dewif" + authentication_v2_file_name = "authentication_file_sr25519.json" + + def __init__(self) -> None: + self.account_name = tools.has_account_defined() + + self.path = Path.home().joinpath( + self.xdg_data_home, + self.program_name, + bc_tools.get_currency(), + self.account_name, + ) + self.path.mkdir(parents=True, exist_ok=True) + + def authentication_file_path(self, check_exist: bool = True) -> Path: + auth_file_path = self.path.joinpath(self.authentication_v1_file_name) + if check_exist and not auth_file_path.is_file(): + tools.click_fail( + f"{auth_file_path} not found for account name: {self.account_name}", + ) + return auth_file_path + + def revocation_path(self, check_exist: bool = True) -> Path: + revocation_path = self.path.joinpath(self.revocation_file_name) + if check_exist and not revocation_path.is_file(): + tools.click_fail( + f"{revocation_path} not found for account name: {self.account_name}", + ) + return revocation_path diff --git a/silkaj/tools.py b/silkaj/tools.py index fc6e11f6..5b58383b 100644 --- a/silkaj/tools.py +++ b/silkaj/tools.py @@ -36,6 +36,11 @@ def message_exit(message: str) -> None: sys.exit(FAILURE_EXIT_STATUS) +@click.pass_context +def click_fail(context: click.Context, message: str) -> None: + context.fail(message) + + class MutuallyExclusiveOption(click.Option): def __init__(self, *args: Any, **kwargs: Any) -> None: self.mutually_exclusive = set(kwargs.pop("mutually_exclusive", [])) diff --git a/tests/unit/test_account_storage.py b/tests/unit/test_account_storage.py new file mode 100644 index 00000000..57b7251a --- /dev/null +++ b/tests/unit/test_account_storage.py @@ -0,0 +1,49 @@ +# Copyright 2016-2025 Maël Azimi <m.a@moul.re> +# +# Silkaj is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Silkaj 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 Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Silkaj. If not, see <https://www.gnu.org/licenses/>. + +from pathlib import Path +from unittest.mock import Mock + +import pytest + +from silkaj.account_storage import AccountStorage +from silkaj.blockchain import tools +from tests import helpers + + +@pytest.mark.parametrize( + ("account_name", "currency"), + [ + ("test", "g1"), + ("toto", "g1-test"), + ], +) +def test_account_storage_account(account_name, currency, monkeypatch): + def patched_get_currency(): + return currency + + helpers.define_click_context(account_name=account_name) + patched_pathlib_mkdir = Mock() + monkeypatch.setattr(Path, "mkdir", patched_pathlib_mkdir) + monkeypatch.setattr(tools, "get_currency", patched_get_currency) + + account_storage = AccountStorage() + assert account_storage.path == Path.home().joinpath( + account_storage.xdg_data_home, + account_storage.program_name, + currency, + account_name, + ) + patched_pathlib_mkdir.assert_called_once() -- GitLab