diff --git a/aiida_optimade/mappers/entries.py b/aiida_optimade/mappers/entries.py index d98fe465..8c7111ff 100644 --- a/aiida_optimade/mappers/entries.py +++ b/aiida_optimade/mappers/entries.py @@ -21,6 +21,12 @@ class ResourceMapper(OptimadeResourceMapper): "relationships", "links", "meta", + "description", + "related", + "structures", + "data", + "self", + "references", } @classmethod diff --git a/aiida_optimade/mappers/structures.py b/aiida_optimade/mappers/structures.py index c7f67b41..d2fa8dff 100644 --- a/aiida_optimade/mappers/structures.py +++ b/aiida_optimade/mappers/structures.py @@ -22,7 +22,9 @@ class StructureMapper(ResourceMapper): "data.core.cif.CifData.": CifDataTranslator, "data.core.structure.StructureData.": StructureDataTranslator, } - REQUIRED_ATTRIBUTES = set(StructureResourceAttributes.schema().get("required")) + REQUIRED_ATTRIBUTES = set( + StructureResourceAttributes.model_json_schema().get("required") + ) # This should be REQUIRED_FIELDS, but should be set as such in `optimade` ENTRY_RESOURCE_CLASS = StructureResource diff --git a/requirements.txt b/requirements.txt index b7d12e09..1a4d8035 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ -optimade[server]~=0.25.3 -aiida-core~=2.4.0 -pymatgen>=2019.7.2,!=2019.9.7,<2024.6.5 +optimade[server]~=1.0.1 +aiida-core~=2.5.0 +#pymatgen>=2019.7.2,!=2019.9.7,<2024.6.5 # Dependencies used directly in this package, but included through other dependencies: # aiida-core: diff --git a/tests/cli/conftest.py b/tests/cli/conftest.py index 8f20802e..5c4b5224 100644 --- a/tests/cli/conftest.py +++ b/tests/cli/conftest.py @@ -11,7 +11,7 @@ @pytest.fixture -def aiida_test_profile() -> str: +def aiida_test_profile_name() -> str: """Return AiiDA test profile used for AiiDA-OPTIMADE""" from aiida_optimade.cli.cmd_aiida_optimade import AIIDA_OPTIMADE_TEST_PROFILE @@ -19,7 +19,7 @@ def aiida_test_profile() -> str: @pytest.fixture -def run_cli_command(aiida_test_profile: str): +def run_cli_command(aiida_test_profile_name: str): """Run a `click` command with the given options. The call will raise if the command triggered an exception or the exit code returned @@ -43,10 +43,10 @@ def _run_cli_command( import traceback runner = click.testing.CliRunner() - profile = os.getenv("AIIDA_PROFILE", aiida_test_profile) + profile = os.getenv("AIIDA_PROFILE", aiida_test_profile_name) if profile == "test_profile": # This is for local tests only - profile = aiida_test_profile + profile = aiida_test_profile_name result = runner.invoke(command, options or [], env={"AIIDA_PROFILE": profile}) if raises: @@ -68,7 +68,7 @@ def _run_cli_command( @pytest.fixture -def run_and_terminate_server(aiida_test_profile: str): +def run_and_terminate_server(aiida_test_profile_name: str): """Run a `click` command with the given options. The call will raise if the command triggered an exception or the exit code returned @@ -89,10 +89,10 @@ def _run_and_terminate_server( :param raises: Whether the command is expected to raise an exception :return: Test result """ - profile = os.getenv("AIIDA_PROFILE", aiida_test_profile) + profile = os.getenv("AIIDA_PROFILE", aiida_test_profile_name) if profile == "test_profile": # This is for local tests only - profile = aiida_test_profile + profile = aiida_test_profile_name args = ["aiida-optimade", "-p", profile] args.append(command) diff --git a/tests/cli/test_calc.py b/tests/cli/test_calc.py index 7bc9d1b8..50282495 100644 --- a/tests/cli/test_calc.py +++ b/tests/cli/test_calc.py @@ -11,7 +11,7 @@ os.getenv("PYTEST_OPTIMADE_CONFIG_FILE") is not None, reason="Test is not for MongoDB", ) -def test_calc_all_new(run_cli_command, aiida_profile, top_dir, caplog): +def test_calc_all_new(run_cli_command, aiida_profile_populated, top_dir, caplog): """Test `aiida-optimade -p profile_name calc` works for non-existent fields. By "non-existent" the meaning is calculating fields that don't already exist for @@ -24,7 +24,7 @@ def test_calc_all_new(run_cli_command, aiida_profile, top_dir, caplog): from aiida_optimade.translators.entities import AiidaEntityTranslator # Clear database and get initialized_structure_nodes.aiida - aiida_profile.reset_db() + aiida_profile_populated.clear_profile() archive = top_dir.joinpath("tests/cli/static/initialized_structure_nodes.aiida") import_archive(archive) @@ -97,7 +97,7 @@ def test_calc_all_new(run_cli_command, aiida_profile, top_dir, caplog): ), caplog.text # Repopulate database with the "proper" test data - aiida_profile.reset_db() + aiida_profile_populated.clear_profile() original_data = top_dir.joinpath("tests/static/test_structures.aiida") import_archive(original_data) @@ -106,7 +106,7 @@ def test_calc_all_new(run_cli_command, aiida_profile, top_dir, caplog): os.getenv("PYTEST_OPTIMADE_CONFIG_FILE") is not None, reason="Test is not for MongoDB", ) -def test_calc(run_cli_command, aiida_profile, top_dir): +def test_calc(run_cli_command, aiida_profile_populated, top_dir): """Test `aiida-optimade -p profile_name calc` works.""" from aiida import orm from aiida.tools.archive.imports import import_archive @@ -115,7 +115,7 @@ def test_calc(run_cli_command, aiida_profile, top_dir): from aiida_optimade.translators.entities import AiidaEntityTranslator # Clear database and get initialized_structure_nodes.aiida - aiida_profile.reset_db() + aiida_profile_populated.clear_profile() archive = top_dir.joinpath("tests/cli/static/initialized_structure_nodes.aiida") import_archive(archive) @@ -159,7 +159,7 @@ def test_calc(run_cli_command, aiida_profile, top_dir): assert n_structure_data == n_updated_structure_data # Repopulate database with the "proper" test data - aiida_profile.reset_db() + aiida_profile_populated.clear_profile() original_data = top_dir.joinpath("tests/static/test_structures.aiida") import_archive(original_data) @@ -168,7 +168,7 @@ def test_calc(run_cli_command, aiida_profile, top_dir): os.getenv("PYTEST_OPTIMADE_CONFIG_FILE") is not None, reason="Test is not for MongoDB", ) -def test_calc_partially_init(run_cli_command, aiida_profile, top_dir, caplog): +def test_calc_partially_init(run_cli_command, aiida_profile_populated, top_dir, caplog): """Test `aiida-optimade -p profile_name calc` works for a partially initalized DB""" from aiida import orm from aiida.tools.archive.imports import import_archive @@ -177,7 +177,7 @@ def test_calc_partially_init(run_cli_command, aiida_profile, top_dir, caplog): from aiida_optimade.translators.entities import AiidaEntityTranslator # Clear database and get initialized_structure_nodes.aiida - aiida_profile.reset_db() + aiida_profile_populated.clear_profile() archive = top_dir.joinpath("tests/cli/static/initialized_structure_nodes.aiida") import_archive(archive) @@ -256,6 +256,6 @@ def test_calc_partially_init(run_cli_command, aiida_profile, top_dir, caplog): ), caplog.text # Repopulate database with the "proper" test data - aiida_profile.reset_db() + aiida_profile_populated.clear_profile() original_data = top_dir.joinpath("tests/static/test_structures.aiida") import_archive(original_data) diff --git a/tests/cli/test_init.py b/tests/cli/test_init.py index 4c91c0a4..a2362b78 100644 --- a/tests/cli/test_init.py +++ b/tests/cli/test_init.py @@ -11,7 +11,7 @@ os.getenv("PYTEST_OPTIMADE_CONFIG_FILE") is not None, reason="Test is not for MongoDB", ) -def test_init_structuredata(run_cli_command, aiida_profile, top_dir, caplog): +def test_init_structuredata(run_cli_command, aiida_profile_populated, top_dir, caplog): """Test `aiida-optimade -p profile_name init` works for StructureData Nodes. Also, check the `-f/--force` option. @@ -23,7 +23,7 @@ def test_init_structuredata(run_cli_command, aiida_profile, top_dir, caplog): from aiida_optimade.translators.entities import AiidaEntityTranslator # Clear database - aiida_profile.reset_db() + aiida_profile_populated.clear_profile() archive = top_dir.joinpath("tests/cli/static/structure_data_nodes.aiida") import_archive(archive) @@ -83,7 +83,7 @@ def test_init_structuredata(run_cli_command, aiida_profile, top_dir, caplog): ), caplog.text # Repopulate database with the "proper" test data - aiida_profile.reset_db() + aiida_profile_populated.clear_profile() original_data = top_dir.joinpath("tests/static/test_structures.aiida") import_archive(original_data) @@ -92,7 +92,7 @@ def test_init_structuredata(run_cli_command, aiida_profile, top_dir, caplog): os.getenv("PYTEST_OPTIMADE_CONFIG_FILE") is not None, reason="Test is not for MongoDB", ) -def test_init_cifdata(run_cli_command, aiida_profile, top_dir, caplog): +def test_init_cifdata(run_cli_command, aiida_profile_populated, top_dir, caplog): """Test `aiida-optimade -p profile_name init` works for CifData Nodes.""" from aiida import orm from aiida.tools.archive.imports import import_archive @@ -101,7 +101,7 @@ def test_init_cifdata(run_cli_command, aiida_profile, top_dir, caplog): from aiida_optimade.translators.entities import AiidaEntityTranslator # Clear database - aiida_profile.reset_db() + aiida_profile_populated.clear_profile() archive = top_dir.joinpath("tests/cli/static/cif_data_nodes.aiida") import_archive(archive) @@ -137,7 +137,7 @@ def test_init_cifdata(run_cli_command, aiida_profile, top_dir, caplog): ), caplog.text # Repopulate database with the "proper" test data - aiida_profile.reset_db() + aiida_profile_populated.clear_profile() original_data = top_dir.joinpath("tests/static/test_structures.aiida") import_archive(original_data) @@ -145,7 +145,9 @@ def test_init_cifdata(run_cli_command, aiida_profile, top_dir, caplog): @pytest.mark.skipif( os.getenv("PYTEST_OPTIMADE_CONFIG_FILE") is None, reason="Test is only for MongoDB" ) -def test_init_structuredata_mongo(run_cli_command, aiida_profile, top_dir, caplog): +def test_init_structuredata_mongo( + run_cli_command, aiida_profile_populated, top_dir, caplog +): """Test `aiida-optimade -p profile_name init --mongo` works for StructureData Nodes. Also, check the `-f/--force` option. @@ -159,7 +161,7 @@ def test_init_structuredata_mongo(run_cli_command, aiida_profile, top_dir, caplo from aiida_optimade.translators.entities import AiidaEntityTranslator # Clear databases - aiida_profile.reset_db() + aiida_profile_populated.clear_profile() STRUCTURES_MONGO.collection.drop() archive = top_dir.joinpath("tests/cli/static/structure_data_nodes.aiida") @@ -223,7 +225,7 @@ def test_init_structuredata_mongo(run_cli_command, aiida_profile, top_dir, caplo ), caplog.text # Repopulate databases with the "proper" test data - aiida_profile.reset_db() + aiida_profile_populated.clear_profile() import_archive(top_dir.joinpath("tests/static/test_structures.aiida")) STRUCTURES_MONGO.collection.drop() with open(top_dir.joinpath("tests/static/test_structures_mongo.json")) as handle: @@ -234,7 +236,7 @@ def test_init_structuredata_mongo(run_cli_command, aiida_profile, top_dir, caplo @pytest.mark.skipif( os.getenv("PYTEST_OPTIMADE_CONFIG_FILE") is None, reason="Test is only for MongoDB" ) -def test_init_cifdata_mongo(run_cli_command, aiida_profile, top_dir, caplog): +def test_init_cifdata_mongo(run_cli_command, aiida_profile_populated, top_dir, caplog): """Test `aiida-optimade -p profile_name init` works for CifData Nodes.""" import bson.json_util from aiida import orm @@ -245,7 +247,7 @@ def test_init_cifdata_mongo(run_cli_command, aiida_profile, top_dir, caplog): from aiida_optimade.translators.entities import AiidaEntityTranslator # Clear databases - aiida_profile.reset_db() + aiida_profile_populated.clear_profile() STRUCTURES_MONGO.collection.drop() archive = top_dir.joinpath("tests/cli/static/cif_data_nodes.aiida") @@ -284,7 +286,7 @@ def test_init_cifdata_mongo(run_cli_command, aiida_profile, top_dir, caplog): ), caplog.text # Repopulate database with the "proper" test data - aiida_profile.reset_db() + aiida_profile_populated.clear_profile() import_archive(top_dir.joinpath("tests/static/test_structures.aiida")) STRUCTURES_MONGO.collection.drop() with open(top_dir.joinpath("tests/static/test_structures_mongo.json")) as handle: diff --git a/tests/cli/test_run.py b/tests/cli/test_run.py index f41450c9..68ec1567 100644 --- a/tests/cli/test_run.py +++ b/tests/cli/test_run.py @@ -10,17 +10,17 @@ @pytest.fixture -def run_server(aiida_test_profile: str): +def run_server(aiida_test_profile_name: str): """Run the server using `aiida-optimade run` :param options: the list of command line options to pass to `aiida-optimade run` invocation :param raises: whether `aiida-optimade run` is expected to raise an exception """ - profile = os.getenv("AIIDA_PROFILE", aiida_test_profile) + profile = os.getenv("AIIDA_PROFILE", aiida_test_profile_name) if profile == "test_profile": # This is for local tests only - profile = aiida_test_profile + profile = aiida_test_profile_name args = ["aiida-optimade", "-p", profile, "run"] env = dict(os.environ) @@ -115,7 +115,7 @@ def test_logging_precedence(run_and_terminate_server): ), f"output: {output!r}, errors: {errors!r}" -def test_env_var_is_set(run_and_terminate_server, aiida_test_profile: str): +def test_env_var_is_set(run_and_terminate_server, aiida_test_profile_name: str): """Test the AIIDA_PROFILE env var is set The issue with this test, is that the set "AIIDA_PROFILE" environment variable @@ -131,7 +131,7 @@ def test_env_var_is_set(run_and_terminate_server, aiida_test_profile: str): assert fixture_profile is not None if fixture_profile == "test_profile": # This is for local tests only - fixture_profile = aiida_test_profile + fixture_profile = aiida_test_profile_name output, errors = run_and_terminate_server(command="run") assert fixture_profile in output, f"output: {output!r}, errors: {errors!r}" diff --git a/tests/conftest.py b/tests/conftest.py index eb983da4..0410fe1b 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -3,7 +3,8 @@ from pathlib import Path import pytest -from aiida.manage.tests import TestManager + +pytest_plugins = ["aiida.manage.tests.pytest_fixtures"] @pytest.fixture(scope="session") @@ -32,56 +33,42 @@ def setup_config(top_dir) -> None: @pytest.fixture(scope="session", autouse=True) -def aiida_profile(top_dir, setup_config) -> TestManager: - """Load test data for AiiDA test profile - - It is necessary to remove `AIIDA_PROFILE`, since it clashes with the test profile - """ - from aiida import load_profile - from aiida.manage.tests import ( - get_test_backend_name, - get_test_profile_name, - test_manager, - ) +def aiida_profile_populated(top_dir, setup_config, aiida_profile): + """Load test data for AiiDA test profile""" from aiida.tools.archive.imports import import_archive org_env_var = os.getenv("AIIDA_PROFILE") test_env_var = os.getenv("PYTEST_OPTIMADE_CONFIG_FILE") try: - # Setup profile - with test_manager( - backend=get_test_backend_name(), profile_name=get_test_profile_name() - ) as manager: - manager.reset_db() - - profile = load_profile() - # If test locally `AIIDA_TEST_PROFILE` may not set and `test_profile` will be used - assert profile.name in ["test_profile", "test_psql_dos"] - os.environ["AIIDA_PROFILE"] = profile.name - - # Use AiiDA DB - import_archive(top_dir.joinpath("tests/static/test_structures.aiida")) - - if test_env_var: - # Use MongoDB - assert os.getenv("OPTIMADE_CONFIG_FILE", "") == test_env_var, ( - "Config file env var not set prior to updating the MongoDB! Found " - "it to be a MongoDB backend, since PYTEST_OPTIMADE_CONFIG_FILE is " - f"set to {test_env_var}" - ) - import bson.json_util - - from aiida_optimade.routers.structures import STRUCTURES_MONGO - - STRUCTURES_MONGO.collection.drop() - with open( - top_dir.joinpath("tests/static/test_structures_mongo.json") - ) as handle: - data = bson.json_util.loads(handle.read()) - STRUCTURES_MONGO.collection.insert_many(data) - - yield manager + aiida_profile.clear_profile() + + # If test locally `AIIDA_TEST_PROFILE` may not set and `test_profile` will be used + # assert profile.name in ["test_profile", "test_psql_dos"] + os.environ["AIIDA_PROFILE"] = aiida_profile.name + + # Use AiiDA DB + import_archive(top_dir.joinpath("tests/static/test_structures.aiida")) + + if test_env_var: + # Use MongoDB + assert os.getenv("OPTIMADE_CONFIG_FILE", "") == test_env_var, ( + "Config file env var not set prior to updating the MongoDB! Found " + "it to be a MongoDB backend, since PYTEST_OPTIMADE_CONFIG_FILE is " + f"set to {test_env_var}" + ) + import bson.json_util + + from aiida_optimade.routers.structures import STRUCTURES_MONGO + + STRUCTURES_MONGO.collection.drop() + with open( + top_dir.joinpath("tests/static/test_structures_mongo.json") + ) as handle: + data = bson.json_util.loads(handle.read()) + STRUCTURES_MONGO.collection.insert_many(data) + + yield aiida_profile finally: if org_env_var is not None: os.environ["AIIDA_PROFILE"] = org_env_var