From 2e2859586a4df5a5f8c7b4cc9b65b0a5a320f6d7 Mon Sep 17 00:00:00 2001 From: Ali Date: Sun, 22 Sep 2024 21:00:58 +0200 Subject: [PATCH 1/6] version control on sqlite --- src/aiida/cmdline/commands/cmd_status.py | 17 +++++++++++- src/aiida/common/exceptions.py | 7 +++++ src/aiida/storage/sqlite_dos/backend.py | 2 ++ src/aiida/storage/sqlite_zip/backend.py | 19 ++++++++++++- tests/cmdline/commands/test_profile.py | 29 ++++++++++++++++++++ tests/cmdline/commands/test_status.py | 32 ++++++++++++++++++++++ tests/storage/sqlite_dos/test_backend.py | 14 ++++++++++ tests/storage/sqlite_zip/test_backend.py | 35 +++++++++++++++++++++++- 8 files changed, 152 insertions(+), 3 deletions(-) diff --git a/src/aiida/cmdline/commands/cmd_status.py b/src/aiida/cmdline/commands/cmd_status.py index f3c32327dc..d3666738e4 100644 --- a/src/aiida/cmdline/commands/cmd_status.py +++ b/src/aiida/cmdline/commands/cmd_status.py @@ -16,7 +16,12 @@ from aiida.cmdline.commands.cmd_verdi import verdi from aiida.cmdline.params import options from aiida.cmdline.utils import echo -from aiida.common.exceptions import CorruptStorage, IncompatibleStorageSchema, UnreachableStorage +from aiida.common.exceptions import ( + CorruptStorage, + IncompatibleExternalDependencies, + IncompatibleStorageSchema, + UnreachableStorage, +) from aiida.common.log import override_log_level from aiida.common.warnings import warn_deprecation @@ -96,6 +101,12 @@ def verdi_status(print_traceback, no_rmq): storage_cls = profile.storage_cls storage_head_version = storage_cls.version_head() storage_backend = storage_cls(profile) + + if storage_cls.__name__ in ['SqliteZipBackend', 'SqliteDosStorage']: + from aiida.storage.sqlite_zip.backend import validate_sqlite_version + + validate_sqlite_version() + except UnreachableStorage as exc: message = "Unable to connect to profile's storage." print_status(ServiceStatus.DOWN, 'storage', message, exception=exc, print_traceback=print_traceback) @@ -111,6 +122,10 @@ def verdi_status(print_traceback, no_rmq): message = 'Storage is corrupted.' print_status(ServiceStatus.DOWN, 'storage', message, exception=exc, print_traceback=print_traceback) exit_code = ExitCode.CRITICAL + except IncompatibleExternalDependencies as exc: + message = "Storage backend version doesn't satisfy the requirements of the installed AiiDA version. " + print_status(ServiceStatus.DOWN, 'storage', message, exception=exc) + exit_code = ExitCode.CRITICAL except Exception as exc: message = "Unable to instatiate profile's storage." print_status(ServiceStatus.ERROR, 'storage', message, exception=exc, print_traceback=print_traceback) diff --git a/src/aiida/common/exceptions.py b/src/aiida/common/exceptions.py index 6fdd1c2620..e482bb2ffc 100644 --- a/src/aiida/common/exceptions.py +++ b/src/aiida/common/exceptions.py @@ -200,6 +200,13 @@ class IncompatibleDatabaseSchema(ConfigurationError): # noqa: N818 """ +class IncompatibleExternalDependencies(ConfigurationError): # noqa: N818 + """Raised when incomptabale external depencies are found. + + This could happen, when the dependency is not a python package and therefore not checked during installation. + """ + + class IncompatibleStorageSchema(IncompatibleDatabaseSchema): """Raised when the storage schema is incompatible with that of the code.""" diff --git a/src/aiida/storage/sqlite_dos/backend.py b/src/aiida/storage/sqlite_dos/backend.py index 7be70f4a1c..4bbfee40f1 100644 --- a/src/aiida/storage/sqlite_dos/backend.py +++ b/src/aiida/storage/sqlite_dos/backend.py @@ -31,6 +31,7 @@ from aiida.storage.log import MIGRATE_LOGGER from aiida.storage.psql_dos.models.settings import DbSetting from aiida.storage.sqlite_zip import models, orm +from aiida.storage.sqlite_zip.backend import validate_sqlite_version from aiida.storage.sqlite_zip.utils import create_sqla_engine from ..migrations import TEMPLATE_INVALID_SCHEMA_VERSION @@ -226,6 +227,7 @@ def filepath_database(self) -> Path: @classmethod def initialise(cls, profile: Profile, reset: bool = False) -> bool: + validate_sqlite_version() filepath = Path(profile.storage_config['filepath']) try: diff --git a/src/aiida/storage/sqlite_zip/backend.py b/src/aiida/storage/sqlite_zip/backend.py index 771660d315..aaba54b90a 100644 --- a/src/aiida/storage/sqlite_zip/backend.py +++ b/src/aiida/storage/sqlite_zip/backend.py @@ -24,7 +24,7 @@ from sqlalchemy.orm import Session from aiida import __version__ -from aiida.common.exceptions import ClosedStorage, CorruptStorage +from aiida.common.exceptions import ClosedStorage, CorruptStorage, IncompatibleExternalDependencies from aiida.common.log import AIIDA_LOGGER from aiida.manage import Profile from aiida.orm.entities import EntityTypes @@ -45,6 +45,21 @@ __all__ = ('SqliteZipBackend',) LOGGER = AIIDA_LOGGER.getChild(__file__) +SUPPORTED_VERSION = '3.35.0' # minimum supported version of sqlite + + +def validate_sqlite_version(): + import sqlite3 + + from packaging.version import parse + + sqlite_installed_version = parse(sqlite3.sqlite_version) + if sqlite_installed_version < parse(SUPPORTED_VERSION): + message = ( + f'Storage backend requires sqlite {parse(SUPPORTED_VERSION)} or higher.' + f' But you have {sqlite_installed_version} installed.' + ) + raise IncompatibleExternalDependencies(message) class SqliteZipBackend(StorageBackend): @@ -89,6 +104,7 @@ def version_head(cls) -> str: def create_profile(filepath: str | Path, options: dict | None = None) -> Profile: """Create a new profile instance for this backend, from the path to the zip file.""" profile_name = Path(filepath).name + validate_sqlite_version() return Profile( profile_name, { @@ -111,6 +127,7 @@ def initialise(cls, profile: 'Profile', reset: bool = False) -> bool: tests having run. :returns: ``True`` if the storage was initialised by the function call, ``False`` if it was already initialised. """ + validate_sqlite_version() from archive_path import ZipPath filepath_archive = Path(profile.storage_config['filepath']) diff --git a/tests/cmdline/commands/test_profile.py b/tests/cmdline/commands/test_profile.py index 07b45c2818..894614b6b7 100644 --- a/tests/cmdline/commands/test_profile.py +++ b/tests/cmdline/commands/test_profile.py @@ -162,6 +162,35 @@ def test_delete_force(run_cli_command, mock_profiles, pg_test_cluster): assert 'When the `-f/--force` flag is used either `--delete-data` or `--keep-data`' in result.output +@pytest.mark.parametrize('entry_point', ('core.sqlite_dos', 'core.sqlite_zip')) +def test_setup_with_validating_sqlite_version( + config_psql_dos, run_cli_command, isolated_config, tmp_path, entry_point, monkeypatch +): + """Test the ``verdi profile setup`` command. + Same as `test_setup`, here we check the fucntionality to check sqlite versions, before setting up profiles. + Note that this test should be run before the `test_delete_storage` test. + """ + + if entry_point == 'core.sqlite_zip': + tmp_path = tmp_path / 'archive.aiida' + create_archive([], filename=tmp_path) + + profile_name = 'temp-profile' + options = [entry_point, '-n', '--profile-name', profile_name, '--email', 'email@host', '--filepath', str(tmp_path)] + + # Should raise if installed version is lower than the supported one. + monkeypatch.setattr('aiida.storage.sqlite_zip.backend.SUPPORTED_VERSION', '100.0.0') + result = run_cli_command(cmd_profile.profile_setup, options, use_subprocess=False, raises=True) + # assert f'Storage backend requires sqlite 100.0.0 or higher. But you have' in result.stderr + assert profile_name not in isolated_config.profile_names + + # Should not raise if installed version is higher than the supported one. + monkeypatch.setattr('aiida.storage.sqlite_zip.backend.SUPPORTED_VERSION', '0.0.0') + result = run_cli_command(cmd_profile.profile_setup, options, use_subprocess=False) + assert profile_name in isolated_config.profile_names + assert f'Created new profile `{profile_name}`.' in result.output + + @pytest.mark.parametrize('entry_point', ('core.sqlite_dos', 'core.sqlite_zip')) def test_delete_storage(run_cli_command, isolated_config, tmp_path, entry_point): """Test the ``verdi profile delete`` command with the ``--delete-storage`` option.""" diff --git a/tests/cmdline/commands/test_status.py b/tests/cmdline/commands/test_status.py index a4b81dbfc6..ea0a6d00b8 100644 --- a/tests/cmdline/commands/test_status.py +++ b/tests/cmdline/commands/test_status.py @@ -98,3 +98,35 @@ def storage_cls(*args, **kwargs): result = run_cli_command(cmd_status.verdi_status, raises=True, use_subprocess=False) assert 'Storage is corrupted' in result.output assert result.exit_code is ExitCode.CRITICAL + + +def test_sqlite_version(run_cli_command, monkeypatch): + """Test `verdi status` when the storage is found to be corrupt (e.g. non-matching repository UUIDs).""" + + profile = get_profile() + storage_backend = profile._attributes['storage']['backend'] + # This should be True, only if `pytest -m 'presto'` is used. + # and that is essential to guarantee the funtionality of the code! + if storage_backend in ['core.sqlite_dos', 'core.sqlite_zip']: + # Should raise if installed version is lower than the supported one. + monkeypatch.setattr('aiida.storage.sqlite_zip.backend.SUPPORTED_VERSION', '100.0.0') + result = run_cli_command(cmd_status.verdi_status, use_subprocess=False, raises=True) + assert ( + "Storage backend version doesn't satisfy the requirements of the installed AiiDA version" in result.output + ) + assert ( + 'IncompatibleExternalDependencies: Storage backend requires sqlite 100.0.0 or higher. But you have' + in result.stderr + ) + + # Should not raise if installed version is higher than the supported one. + monkeypatch.setattr('aiida.storage.sqlite_zip.backend.SUPPORTED_VERSION', '0.0.0') + result = run_cli_command(cmd_status.verdi_status, use_subprocess=False) + + else: + from unittest.mock import MagicMock + + mock_ = MagicMock() + monkeypatch.setattr('aiida.storage.sqlite_zip.backend.validate_sqlite_version', mock_) + result = run_cli_command(cmd_status.verdi_status, use_subprocess=False) + assert mock_.call_count == 0 diff --git a/tests/storage/sqlite_dos/test_backend.py b/tests/storage/sqlite_dos/test_backend.py index 61988db1e9..769116c96a 100644 --- a/tests/storage/sqlite_dos/test_backend.py +++ b/tests/storage/sqlite_dos/test_backend.py @@ -1,6 +1,7 @@ """Tests for :mod:`aiida.storage.sqlite_dos.backend`.""" import pathlib +from unittest.mock import MagicMock import pytest from aiida.storage.sqlite_dos.backend import FILENAME_CONTAINER, FILENAME_DATABASE, SqliteDosStorage @@ -38,3 +39,16 @@ def test_backup(aiida_config, aiida_profile_factory, tmp_path, manager): dirpath_backup = filepath_last.resolve() assert (dirpath_backup / FILENAME_DATABASE).exists() assert (dirpath_backup / FILENAME_CONTAINER).exists() + + +def test_initialise_version_check(tmp_path, monkeypatch): + """Test :meth:`aiida.storage.sqlite_zip.backend.SqliteZipBackend.create_profile` + only if calls on validate_sqlite_version.""" + + mock_ = MagicMock() + monkeypatch.setattr('aiida.storage.sqlite_dos.backend.validate_sqlite_version', mock_) + + # Here, we don't care about functionality of initialise itself, but only that it calls validate_sqlite_version. + with pytest.raises(AttributeError): + SqliteDosStorage.initialise('') + mock_.assert_called_once() diff --git a/tests/storage/sqlite_zip/test_backend.py b/tests/storage/sqlite_zip/test_backend.py index 7b42f8455c..47d5d16936 100644 --- a/tests/storage/sqlite_zip/test_backend.py +++ b/tests/storage/sqlite_zip/test_backend.py @@ -1,9 +1,11 @@ """Tests for :mod:`aiida.storage.sqlite_zip.backend`.""" import pathlib +from unittest.mock import MagicMock import pytest -from aiida.storage.sqlite_zip.backend import SqliteZipBackend +from aiida.common.exceptions import IncompatibleExternalDependencies +from aiida.storage.sqlite_zip.backend import SqliteZipBackend, validate_sqlite_version from aiida.storage.sqlite_zip.migrator import validate_storage from pydantic_core import ValidationError @@ -62,3 +64,34 @@ def test_model(): model = SqliteZipBackend.Model(filepath=filepath.name) assert pathlib.Path(model.filepath).is_absolute() + + +def test_validate_sqlite_version(monkeypatch): + """Test :meth:`aiida.storage.sqlite_zip.backend.validate_sqlite_version`.""" + + # Test when sqlite version is not supported, should read sqlite version from sqlite3.sqlite_version + monkeypatch.setattr('sqlite3.sqlite_version', '0.0.0') + monkeypatch.setattr('aiida.storage.sqlite_zip.backend.SUPPORTED_VERSION', '100.0.0') + with pytest.raises( + IncompatibleExternalDependencies, match=r'.*Storage backend requires sqlite 100.0.0 or higher.*' + ): + validate_sqlite_version() + + # Test when sqlite version is supported + monkeypatch.setattr('sqlite3.sqlite_version', '100.0.0') + monkeypatch.setattr('aiida.storage.sqlite_zip.backend.SUPPORTED_VERSION', '0.0.0') + validate_sqlite_version() + + +def test_initialise_version_check(tmp_path, monkeypatch): + """Test :meth:`aiida.storage.sqlite_zip.backend.SqliteZipBackend.create_profile` + only if calls on validate_sqlite_version.""" + + filepath_archive = tmp_path / 'archive.zip' + + mock_ = MagicMock() + monkeypatch.setattr('aiida.storage.sqlite_zip.backend.validate_sqlite_version', mock_) + profile = SqliteZipBackend.create_profile(filepath_archive) + assert mock_.call_count == 1 + SqliteZipBackend.initialise(profile) + assert mock_.call_count == 2 From d178a5b63ccf33ce1d950956180b9ce2b5133714 Mon Sep 17 00:00:00 2001 From: Ali Date: Thu, 10 Oct 2024 12:35:45 +0200 Subject: [PATCH 2/6] review applied --- src/aiida/cmdline/commands/cmd_status.py | 17 +---------------- src/aiida/storage/sqlite_dos/backend.py | 4 ++++ src/aiida/storage/sqlite_zip/backend.py | 2 +- tests/cmdline/commands/test_profile.py | 2 +- tests/storage/sqlite_zip/test_backend.py | 15 --------------- 5 files changed, 7 insertions(+), 33 deletions(-) diff --git a/src/aiida/cmdline/commands/cmd_status.py b/src/aiida/cmdline/commands/cmd_status.py index d3666738e4..f3c32327dc 100644 --- a/src/aiida/cmdline/commands/cmd_status.py +++ b/src/aiida/cmdline/commands/cmd_status.py @@ -16,12 +16,7 @@ from aiida.cmdline.commands.cmd_verdi import verdi from aiida.cmdline.params import options from aiida.cmdline.utils import echo -from aiida.common.exceptions import ( - CorruptStorage, - IncompatibleExternalDependencies, - IncompatibleStorageSchema, - UnreachableStorage, -) +from aiida.common.exceptions import CorruptStorage, IncompatibleStorageSchema, UnreachableStorage from aiida.common.log import override_log_level from aiida.common.warnings import warn_deprecation @@ -101,12 +96,6 @@ def verdi_status(print_traceback, no_rmq): storage_cls = profile.storage_cls storage_head_version = storage_cls.version_head() storage_backend = storage_cls(profile) - - if storage_cls.__name__ in ['SqliteZipBackend', 'SqliteDosStorage']: - from aiida.storage.sqlite_zip.backend import validate_sqlite_version - - validate_sqlite_version() - except UnreachableStorage as exc: message = "Unable to connect to profile's storage." print_status(ServiceStatus.DOWN, 'storage', message, exception=exc, print_traceback=print_traceback) @@ -122,10 +111,6 @@ def verdi_status(print_traceback, no_rmq): message = 'Storage is corrupted.' print_status(ServiceStatus.DOWN, 'storage', message, exception=exc, print_traceback=print_traceback) exit_code = ExitCode.CRITICAL - except IncompatibleExternalDependencies as exc: - message = "Storage backend version doesn't satisfy the requirements of the installed AiiDA version. " - print_status(ServiceStatus.DOWN, 'storage', message, exception=exc) - exit_code = ExitCode.CRITICAL except Exception as exc: message = "Unable to instatiate profile's storage." print_status(ServiceStatus.ERROR, 'storage', message, exception=exc, print_traceback=print_traceback) diff --git a/src/aiida/storage/sqlite_dos/backend.py b/src/aiida/storage/sqlite_dos/backend.py index 4bbfee40f1..acde92c5e0 100644 --- a/src/aiida/storage/sqlite_dos/backend.py +++ b/src/aiida/storage/sqlite_dos/backend.py @@ -244,6 +244,10 @@ def initialise(cls, profile: Profile, reset: bool = False) -> bool: return super().initialise(profile, reset) + def __init__(self, profile: Profile) -> None: + validate_sqlite_version() + super().__init__(profile) + def __str__(self) -> str: state = 'closed' if self.is_closed else 'open' return f'SqliteDosStorage[{self.filepath_root}]: {state},' diff --git a/src/aiida/storage/sqlite_zip/backend.py b/src/aiida/storage/sqlite_zip/backend.py index aaba54b90a..deb80ee9ae 100644 --- a/src/aiida/storage/sqlite_zip/backend.py +++ b/src/aiida/storage/sqlite_zip/backend.py @@ -104,7 +104,6 @@ def version_head(cls) -> str: def create_profile(filepath: str | Path, options: dict | None = None) -> Profile: """Create a new profile instance for this backend, from the path to the zip file.""" profile_name = Path(filepath).name - validate_sqlite_version() return Profile( profile_name, { @@ -185,6 +184,7 @@ def migrate(cls, profile: Profile): def __init__(self, profile: Profile): from .migrator import validate_storage + validate_sqlite_version() super().__init__(profile) self._path = Path(profile.storage_config['filepath']) validate_storage(self._path) diff --git a/tests/cmdline/commands/test_profile.py b/tests/cmdline/commands/test_profile.py index 894614b6b7..6daf05a529 100644 --- a/tests/cmdline/commands/test_profile.py +++ b/tests/cmdline/commands/test_profile.py @@ -167,7 +167,7 @@ def test_setup_with_validating_sqlite_version( config_psql_dos, run_cli_command, isolated_config, tmp_path, entry_point, monkeypatch ): """Test the ``verdi profile setup`` command. - Same as `test_setup`, here we check the fucntionality to check sqlite versions, before setting up profiles. + Same as `test_setup`, here we check the functionality to check sqlite versions, before setting up profiles. Note that this test should be run before the `test_delete_storage` test. """ diff --git a/tests/storage/sqlite_zip/test_backend.py b/tests/storage/sqlite_zip/test_backend.py index 47d5d16936..a4ebba02fe 100644 --- a/tests/storage/sqlite_zip/test_backend.py +++ b/tests/storage/sqlite_zip/test_backend.py @@ -1,7 +1,6 @@ """Tests for :mod:`aiida.storage.sqlite_zip.backend`.""" import pathlib -from unittest.mock import MagicMock import pytest from aiida.common.exceptions import IncompatibleExternalDependencies @@ -81,17 +80,3 @@ def test_validate_sqlite_version(monkeypatch): monkeypatch.setattr('sqlite3.sqlite_version', '100.0.0') monkeypatch.setattr('aiida.storage.sqlite_zip.backend.SUPPORTED_VERSION', '0.0.0') validate_sqlite_version() - - -def test_initialise_version_check(tmp_path, monkeypatch): - """Test :meth:`aiida.storage.sqlite_zip.backend.SqliteZipBackend.create_profile` - only if calls on validate_sqlite_version.""" - - filepath_archive = tmp_path / 'archive.zip' - - mock_ = MagicMock() - monkeypatch.setattr('aiida.storage.sqlite_zip.backend.validate_sqlite_version', mock_) - profile = SqliteZipBackend.create_profile(filepath_archive) - assert mock_.call_count == 1 - SqliteZipBackend.initialise(profile) - assert mock_.call_count == 2 From bb983a6145df28ff90aa93bbeec15fa626f508c1 Mon Sep 17 00:00:00 2001 From: Ali Date: Thu, 10 Oct 2024 13:48:00 +0200 Subject: [PATCH 3/6] fixed an issue with presto --- tests/cmdline/commands/test_status.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/cmdline/commands/test_status.py b/tests/cmdline/commands/test_status.py index ea0a6d00b8..99fc28cd4a 100644 --- a/tests/cmdline/commands/test_status.py +++ b/tests/cmdline/commands/test_status.py @@ -111,9 +111,6 @@ def test_sqlite_version(run_cli_command, monkeypatch): # Should raise if installed version is lower than the supported one. monkeypatch.setattr('aiida.storage.sqlite_zip.backend.SUPPORTED_VERSION', '100.0.0') result = run_cli_command(cmd_status.verdi_status, use_subprocess=False, raises=True) - assert ( - "Storage backend version doesn't satisfy the requirements of the installed AiiDA version" in result.output - ) assert ( 'IncompatibleExternalDependencies: Storage backend requires sqlite 100.0.0 or higher. But you have' in result.stderr From 236f5a312b64141408b10ddf24d4a84c3ab46670 Mon Sep 17 00:00:00 2001 From: Ali Date: Tue, 15 Oct 2024 11:30:46 +0200 Subject: [PATCH 4/6] review applied --- tests/cmdline/commands/test_profile.py | 9 +++------ tests/cmdline/commands/test_status.py | 6 +++--- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/tests/cmdline/commands/test_profile.py b/tests/cmdline/commands/test_profile.py index 6daf05a529..0da3bf8bee 100644 --- a/tests/cmdline/commands/test_profile.py +++ b/tests/cmdline/commands/test_profile.py @@ -163,12 +163,9 @@ def test_delete_force(run_cli_command, mock_profiles, pg_test_cluster): @pytest.mark.parametrize('entry_point', ('core.sqlite_dos', 'core.sqlite_zip')) -def test_setup_with_validating_sqlite_version( - config_psql_dos, run_cli_command, isolated_config, tmp_path, entry_point, monkeypatch -): +def test_setup_with_validating_sqlite_version(run_cli_command, isolated_config, tmp_path, entry_point, monkeypatch): """Test the ``verdi profile setup`` command. - Same as `test_setup`, here we check the functionality to check sqlite versions, before setting up profiles. - Note that this test should be run before the `test_delete_storage` test. + Same as `test_setup`, here we test the functionality to check sqlite versions, before setting up profiles. """ if entry_point == 'core.sqlite_zip': @@ -181,7 +178,7 @@ def test_setup_with_validating_sqlite_version( # Should raise if installed version is lower than the supported one. monkeypatch.setattr('aiida.storage.sqlite_zip.backend.SUPPORTED_VERSION', '100.0.0') result = run_cli_command(cmd_profile.profile_setup, options, use_subprocess=False, raises=True) - # assert f'Storage backend requires sqlite 100.0.0 or higher. But you have' in result.stderr + assert 'Storage backend requires sqlite 100.0.0 or higher. But you have' in result.stderr assert profile_name not in isolated_config.profile_names # Should not raise if installed version is higher than the supported one. diff --git a/tests/cmdline/commands/test_status.py b/tests/cmdline/commands/test_status.py index 99fc28cd4a..bb6a8a453c 100644 --- a/tests/cmdline/commands/test_status.py +++ b/tests/cmdline/commands/test_status.py @@ -101,12 +101,12 @@ def storage_cls(*args, **kwargs): def test_sqlite_version(run_cli_command, monkeypatch): - """Test `verdi status` when the storage is found to be corrupt (e.g. non-matching repository UUIDs).""" + """Test `verdi status` when the sqlite version is incompatible with the required version. + the main functionality of this test is triggered only by the pytest marker 'presto', + through `pytest -m 'presto'`""" profile = get_profile() storage_backend = profile._attributes['storage']['backend'] - # This should be True, only if `pytest -m 'presto'` is used. - # and that is essential to guarantee the funtionality of the code! if storage_backend in ['core.sqlite_dos', 'core.sqlite_zip']: # Should raise if installed version is lower than the supported one. monkeypatch.setattr('aiida.storage.sqlite_zip.backend.SUPPORTED_VERSION', '100.0.0') From 0fa78dd6362e107ea244ec222618396b279e63f5 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 16 Dec 2024 11:30:19 +0000 Subject: [PATCH 5/6] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- tests/storage/sqlite_zip/test_backend.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/storage/sqlite_zip/test_backend.py b/tests/storage/sqlite_zip/test_backend.py index df930f5628..3a57e28580 100644 --- a/tests/storage/sqlite_zip/test_backend.py +++ b/tests/storage/sqlite_zip/test_backend.py @@ -2,7 +2,7 @@ import pathlib -import pytest +import pytest from pydantic_core import ValidationError from aiida.common.exceptions import IncompatibleExternalDependencies From a98f16d44f3b74cd5c01d28fe5e4c75a9a4af2f9 Mon Sep 17 00:00:00 2001 From: Sebastiaan Huber Date: Mon, 16 Dec 2024 23:03:35 +0100 Subject: [PATCH 6/6] simplify test and run for profile with explicit storage backend --- tests/cmdline/commands/test_status.py | 37 ++++++++++----------------- 1 file changed, 13 insertions(+), 24 deletions(-) diff --git a/tests/cmdline/commands/test_status.py b/tests/cmdline/commands/test_status.py index c3f610f4ea..c13ec5875c 100644 --- a/tests/cmdline/commands/test_status.py +++ b/tests/cmdline/commands/test_status.py @@ -101,30 +101,19 @@ def storage_cls(*args, **kwargs): assert result.exit_code is ExitCode.CRITICAL -def test_sqlite_version(run_cli_command, monkeypatch): +@pytest.mark.parametrize('storage_backend', ('core.sqlite_dos', 'core.sqlite_zip')) +def test_sqlite_version(run_cli_command, monkeypatch, isolated_config, aiida_profile_factory, storage_backend): """Test `verdi status` when the sqlite version is incompatible with the required version. the main functionality of this test is triggered only by the pytest marker 'presto', through `pytest -m 'presto'`""" - - profile = get_profile() - storage_backend = profile._attributes['storage']['backend'] - if storage_backend in ['core.sqlite_dos', 'core.sqlite_zip']: - # Should raise if installed version is lower than the supported one. - monkeypatch.setattr('aiida.storage.sqlite_zip.backend.SUPPORTED_VERSION', '100.0.0') - result = run_cli_command(cmd_status.verdi_status, use_subprocess=False, raises=True) - assert ( - 'IncompatibleExternalDependencies: Storage backend requires sqlite 100.0.0 or higher. But you have' - in result.stderr - ) - - # Should not raise if installed version is higher than the supported one. - monkeypatch.setattr('aiida.storage.sqlite_zip.backend.SUPPORTED_VERSION', '0.0.0') - result = run_cli_command(cmd_status.verdi_status, use_subprocess=False) - - else: - from unittest.mock import MagicMock - - mock_ = MagicMock() - monkeypatch.setattr('aiida.storage.sqlite_zip.backend.validate_sqlite_version', mock_) - result = run_cli_command(cmd_status.verdi_status, use_subprocess=False) - assert mock_.call_count == 0 + monkeypatch.setattr('aiida.storage.sqlite_zip.backend.SUPPORTED_VERSION', '100.0.0') + aiida_profile_factory(isolated_config, storage_backend=storage_backend) + result = run_cli_command(cmd_status.verdi_status, use_subprocess=False, raises=True) + assert ( + 'IncompatibleExternalDependencies: Storage backend requires sqlite 100.0.0 or higher. But you have' + in result.stderr + ) + + # Should not raise if installed version is higher than the supported one. + monkeypatch.setattr('aiida.storage.sqlite_zip.backend.SUPPORTED_VERSION', '0.0.0') + result = run_cli_command(cmd_status.verdi_status, use_subprocess=False)