diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5cf58c4..5b75e33 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -63,7 +63,7 @@ jobs: PYTEST_ADDOPTS: "--durations=0" run: | aiida-mock-code || true - pytest --cov=aiida_test_cache tests/ + pytest -s --cov=aiida_test_cache tests/ - name: Upload coverage report uses: codecov/codecov-action@v5 diff --git a/aiida_test_cache/archive_cache/_fixtures.py b/aiida_test_cache/archive_cache/_fixtures.py index 6e6e7a3..9073a83 100644 --- a/aiida_test_cache/archive_cache/_fixtures.py +++ b/aiida_test_cache/archive_cache/_fixtures.py @@ -269,7 +269,7 @@ def mock_objects_to_hash_calcjob(self): if key not in self._hash_ignored_attributes and key not in self._updatable_attributes }, { - entry.link_label: entry.node.base.caching.get_hash() + entry.link_label: entry.node.base.caching.compute_hash() for entry in self.base.links.get_incoming( link_type=(LinkType.INPUT_CALC, LinkType.INPUT_WORK) ) if entry.link_label not in hash_ignored_inputs diff --git a/aiida_test_cache/archive_cache/_utils.py b/aiida_test_cache/archive_cache/_utils.py index da23e14..9c76309 100644 --- a/aiida_test_cache/archive_cache/_utils.py +++ b/aiida_test_cache/archive_cache/_utils.py @@ -57,8 +57,19 @@ class MockNodeCaching(node_caching_class): #type: ignore """ def _get_objects_to_hash(self): + return self.get_objects_to_hash() + + def get_objects_to_hash(self): return hash_objects_func(self) + # Compatibility with aiida-core < 2.6 + # https://github.com/aiidateam/aiida-core/pull/6347 + def compute_hash(self): + try: + return super().compute_hash() + except AttributeError: + return super().get_hash() + monkeypatch.setattr(node_class, "_CLS_NODE_CACHING", MockNodeCaching) diff --git a/aiida_test_cache/mock_code/__init__.py b/aiida_test_cache/mock_code/__init__.py index 871f467..948bb63 100644 --- a/aiida_test_cache/mock_code/__init__.py +++ b/aiida_test_cache/mock_code/__init__.py @@ -16,5 +16,15 @@ "testing_config_action", ) -# ensure aiida's pytest plugin is loaded, which we rely on -pytest_plugins = ['aiida.manage.tests.pytest_fixtures'] +# Load aiida's pytest fixtures +# For aiida-core>=2.6 we load new fixtures which use sqlite backend. +# WARNING: It's not clear what happens if the user later loads +# the old fixtures as well. +from aiida import __version__ as aiida_version +from packaging.version import Version + +if Version(aiida_version) >= Version('2.6.0'): + aiida_core_fixtures = 'aiida.tools.pytest_fixtures' +else: + aiida_core_fixtures = 'aiida.manage.tests.pytest_fixtures' +pytest_plugins = [aiida_core_fixtures] diff --git a/aiida_test_cache/mock_code/_fixtures.py b/aiida_test_cache/mock_code/_fixtures.py index 92d5471..e4ee764 100644 --- a/aiida_test_cache/mock_code/_fixtures.py +++ b/aiida_test_cache/mock_code/_fixtures.py @@ -259,6 +259,6 @@ def _get_mock_code( yield _get_mock_code log_text = log_file.read_text("utf8") - print("AiiDA mock code logging:") if log_text: + print("AiiDA mock code logging:") print(log_text) diff --git a/pyproject.toml b/pyproject.toml index e923cda..dc5ef0a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -41,9 +41,10 @@ keywords = [ urls = {Homepage = "https://aiida-testing.readthedocs.io/"} requires-python = ">=3.9" dependencies = [ - "aiida-core>=2.1,<2.6", + "aiida-core>=2.1,<3", "pytest>=7.0", "voluptuous~=0.12", + "packaging>=21.0", ] [project.optional-dependencies] diff --git a/tests/archive_cache/test_archive_cache.py b/tests/archive_cache/test_archive_cache.py index 0f18178..aed9442 100644 --- a/tests/archive_cache/test_archive_cache.py +++ b/tests/archive_cache/test_archive_cache.py @@ -2,6 +2,7 @@ Test basic usage of the mock code on examples using aiida-diff. """ import os +from pathlib import Path import pytest from aiida.engine import ToContext, WorkChain, run_get_node @@ -12,6 +13,7 @@ from aiida_test_cache.archive_cache._utils import create_node_archive, load_node_archive CALC_ENTRY_POINT = 'diff' +CWD = Path(__file__).parent #### diff workchain for basic tests @@ -44,7 +46,7 @@ def results(self): @pytest.fixture(name='check_diff_workchain') def check_diff_workchain_fixture(): - """Fixture to check the correct outputs/cachgin of the Diffworkchain + """Fixture to check the correct outputs/caching of the Diffworkchain in the tests in this file""" EXPECTED_DIFF = """1,2c1 @@ -62,16 +64,16 @@ def _check_diff_workchain(res, node, should_have_used_cache=True): #Test if cache was used? diffjob = node.base.links.get_outgoing().get_node_by_label('CALL') - cache_src = diffjob.base.caching.get_cache_source() + assert diffjob.base.caching.is_valid_cache calc_hash = diffjob.base.caching.get_hash() assert calc_hash == EXPECTED_HASH, f'Hash mismatch. hashed objects: {diffjob.base.caching._get_objects_to_hash()}' #Make sure that the cache was used if it should have been if should_have_used_cache: - assert cache_src is not None + assert diffjob.base.caching.is_created_from_cache, "Workchain did not use cache even though it should have" else: - assert cache_src is None + assert not diffjob.base.caching.is_created_from_cache, "Workchain used the cache even though it shouldn't have" return _check_diff_workchain @@ -79,7 +81,9 @@ def _check_diff_workchain(res, node, should_have_used_cache=True): #### tests -def test_create_node_archive(mock_code_factory, generate_diff_inputs, clear_database, tmp_path): +def test_create_node_archive( + aiida_profile_clean, mock_code_factory, generate_diff_inputs, tmp_path +): """ Basic test of the create node archive fixture functionality, runs diff workchain and creates archive, check if archive was created @@ -88,7 +92,7 @@ def test_create_node_archive(mock_code_factory, generate_diff_inputs, clear_data inputs = {'diff': generate_diff_inputs()} mock_code = mock_code_factory( label='diff', - data_dir_abspath=os.path.join(os.path.dirname(os.path.abspath(__file__)), 'calc_data'), + data_dir_abspath=CWD / 'calc_data', entry_point=CALC_ENTRY_POINT, ignore_paths=('_aiidasubmit.sh', 'file*') ) @@ -110,7 +114,7 @@ def test_create_node_archive(mock_code_factory, generate_diff_inputs, clear_data assert os.path.isfile(archive_path) -def test_load_node_archive(clear_database, absolute_archive_path): +def test_load_node_archive(aiida_profile_clean, absolute_archive_path): """Basic test of the load node archive fixture functionality, check if archive is loaded""" full_archive_path = absolute_archive_path('diff_workchain.tar.gz') @@ -124,12 +128,12 @@ def test_load_node_archive(clear_database, absolute_archive_path): assert n_nodes == 9 -def test_mock_hash_codes(mock_code_factory, clear_database, liberal_hash): +def test_mock_hash_codes(aiida_profile_clean, mock_code_factory, liberal_hash): """test if mock of _get_objects_to_hash works for Code and Calcs""" mock_code = mock_code_factory( label='diff', - data_dir_abspath=os.path.join(os.path.dirname(os.path.abspath(__file__)), 'calc_data'), + data_dir_abspath=CWD / 'calc_data', entry_point=CALC_ENTRY_POINT, ignore_paths=('_aiidasubmit.sh', 'file*') ) @@ -138,21 +142,20 @@ def test_mock_hash_codes(mock_code_factory, clear_database, liberal_hash): @pytest.mark.parametrize( - 'archive_path', [ - os.path.join(os.path.dirname(os.path.abspath(__file__)), 'caches/test_workchain.tar.gz'), - 'test_workchain.tar.gz' - ] + 'archive_path', [CWD / 'caches/test_workchain.tar.gz', 'test_workchain.tar.gz'] ) def test_enable_archive_cache( - archive_path, aiida_local_code_factory, generate_diff_inputs, enable_archive_cache, - clear_database, check_diff_workchain + archive_path, aiida_profile_clean, aiida_code_installed, generate_diff_inputs, + enable_archive_cache, check_diff_workchain ): """ Basic test of the enable_archive_cache fixture """ inputs = {'diff': generate_diff_inputs()} - diff_code = aiida_local_code_factory(executable='diff', entry_point='diff') + diff_code = aiida_code_installed( + filepath_executable='diff', default_calc_job_plugin=CALC_ENTRY_POINT + ) diff_code.store() inputs['diff']['code'] = diff_code with enable_archive_cache(archive_path, calculation_class=CalculationFactory(CALC_ENTRY_POINT)): @@ -162,7 +165,7 @@ def test_enable_archive_cache( def test_enable_archive_cache_non_existent( - aiida_local_code_factory, generate_diff_inputs, enable_archive_cache, clear_database, + aiida_profile_clean, aiida_code_installed, generate_diff_inputs, enable_archive_cache, tmp_path_factory, check_diff_workchain ): """ @@ -171,7 +174,9 @@ def test_enable_archive_cache_non_existent( """ inputs = {'diff': generate_diff_inputs()} - diff_code = aiida_local_code_factory(executable='diff', entry_point='diff') + diff_code = aiida_code_installed( + filepath_executable='diff', default_calc_job_plugin=CALC_ENTRY_POINT + ) diff_code.store() inputs['diff']['code'] = diff_code diff --git a/tests/conftest.py b/tests/conftest.py index 3ceba4a..317c90e 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -2,11 +2,30 @@ Configuration file for pytest tests of aiida-test-cache. """ import pytest +from aiida import __version__ as aiida_version +from packaging.version import Version pytest_plugins = [ 'pytester', ] +# Compatibility with old aiida-core fixtures +if Version(aiida_version) < Version('2.6.0'): + + @pytest.fixture + def aiida_profile_clean(clear_database): + pass + + @pytest.fixture + def aiida_code_installed(aiida_local_code_factory): + + def _code(filepath_executable, default_calc_job_plugin): + return aiida_local_code_factory( + executable=filepath_executable, entry_point=default_calc_job_plugin + ) + + return _code + @pytest.fixture def generate_diff_inputs(datadir):