From a46198a55c5431be37b04d6af8fe1918d80c0cbf Mon Sep 17 00:00:00 2001 From: Eli Chadwick Date: Mon, 5 Jan 2026 11:31:44 +0000 Subject: [PATCH 1/5] tweaks to root data entity targeting --- .../profiles/five-safes-crate/should/12_check_phase.ttl | 2 +- .../profiles/five-safes-crate/should/4_sign_off.ttl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rocrate_validator/profiles/five-safes-crate/should/12_check_phase.ttl b/rocrate_validator/profiles/five-safes-crate/should/12_check_phase.ttl index 4cd77608..9082ea68 100644 --- a/rocrate_validator/profiles/five-safes-crate/should/12_check_phase.ttl +++ b/rocrate_validator/profiles/five-safes-crate/should/12_check_phase.ttl @@ -70,7 +70,7 @@ five-safes-crate:CheckValueObjectShouldPointToRootDataEntity sh:name "object" ; sh:path schema:object ; sh:minCount 1 ; - sh:hasValue ro-crate:RootDataEntity ; + sh:class ro-crate:RootDataEntity ; sh:severity sh:Warning ; sh:message "`CheckValue` --> `object` SHOULD point to the root of the RO-Crate" ; ] . diff --git a/rocrate_validator/profiles/five-safes-crate/should/4_sign_off.ttl b/rocrate_validator/profiles/five-safes-crate/should/4_sign_off.ttl index d671a0d9..99100acf 100644 --- a/rocrate_validator/profiles/five-safes-crate/should/4_sign_off.ttl +++ b/rocrate_validator/profiles/five-safes-crate/should/4_sign_off.ttl @@ -26,7 +26,7 @@ # There SHOULD be a Sign-Off Phase five-safes-crate:SignOffPhase a sh:NodeShape ; - sh:targetNode <./> ; + sh:targetClass ro-crate:RootDataEntity ; sh:description "Check the Sign-Off Phase" ; sh:sparql [ sh:select """ From f520d72fe9fbb9bba68f1e857e1fd107e5124927 Mon Sep 17 00:00:00 2001 From: Eli Chadwick Date: Mon, 5 Jan 2026 13:00:14 +0000 Subject: [PATCH 2/5] simplify & correct sparql check for validation phase object --- .../should/13_validation_phase.ttl | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/rocrate_validator/profiles/five-safes-crate/should/13_validation_phase.ttl b/rocrate_validator/profiles/five-safes-crate/should/13_validation_phase.ttl index 6558715f..cb2b1813 100644 --- a/rocrate_validator/profiles/five-safes-crate/should/13_validation_phase.ttl +++ b/rocrate_validator/profiles/five-safes-crate/should/13_validation_phase.ttl @@ -65,24 +65,16 @@ five-safes-crate:ValidationCheckObjectShouldPointToRootDataEntity """ ; ] ; - sh:sparql [ - a sh:SPARQLConstraint ; + sh:property [ + a sh:PropertyShape ; sh:name "object" ; - sh:select """ - PREFIX schema: - PREFIX rocrate: - SELECT $this - WHERE { - FILTER NOT EXISTS { - $this schema:object rocrate:RootDataEntity . - } - } - """ ; + sh:path schema:object ; + sh:minCount 1 ; + sh:class ro-crate:RootDataEntity ; sh:severity sh:Warning ; sh:message "`ValidationCheck` --> `object` SHOULD point to the root of the RO-Crate" ; ] . - five-safes-crate:ValidationCheckInstrumentShouldPointToEntityWithSpecificId a sh:NodeShape ; sh:name "ValidationCheck" ; From a0e72adadae4b8e4d06982ba52a007c92be8b5e8 Mon Sep 17 00:00:00 2001 From: Eli Chadwick Date: Mon, 5 Jan 2026 13:35:56 +0000 Subject: [PATCH 3/5] allow do_entity_test to accept arbitrary settings --- tests/shared.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/shared.py b/tests/shared.py index a07d93d1..5bf32c28 100644 --- a/tests/shared.py +++ b/tests/shared.py @@ -110,9 +110,12 @@ def do_entity_test( rocrate_relative_root_path: Optional[str] = None, metadata_only: bool = False, metadata_dict: Optional[dict] = None, + **kwargs, ): """ - Shared function to test a RO-Crate entity + Shared function to test a RO-Crate entity. + + Additional keyword arguments (kwargs) are passed along to initialise ValidationSettings. """ assert not ( rocrate_entity_patch and rocrate_entity_mod_sparql @@ -186,7 +189,8 @@ def do_entity_test( "rocrate_relative_root_path": rocrate_relative_root_path, "metadata_only": metadata_only, "metadata_dict": metadata_dict, - } + }, + **kwargs, ) ) logger.debug("Expected validation result: %s", expected_validation_result) From e85ea5f825b98e789633226343da36e950e39f88 Mon Sep 17 00:00:00 2001 From: Eli Chadwick Date: Mon, 5 Jan 2026 13:36:41 +0000 Subject: [PATCH 4/5] test RECOMMENDED checks pass for valid crates --- .../five-safes-crate/test_valid_5src.py | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/tests/integration/profiles/five-safes-crate/test_valid_5src.py b/tests/integration/profiles/five-safes-crate/test_valid_5src.py index 7de8c869..4bbbff2a 100644 --- a/tests/integration/profiles/five-safes-crate/test_valid_5src.py +++ b/tests/integration/profiles/five-safes-crate/test_valid_5src.py @@ -13,7 +13,9 @@ # limitations under the License. import logging +import pytest +from rocrate_validator import services from rocrate_validator.models import Severity from tests.conftest import SKIP_LOCAL_DATA_ENTITY_EXISTENCE_CHECK_IDENTIFIER from tests.ro_crates import ValidROC @@ -22,6 +24,18 @@ logger = logging.getLogger(__name__) logger.setLevel(logging.DEBUG) +# Dynamically fetch the SKIP_WEB_RESOURCE_AVAILABILITY_IDENTIFIER +rocrate_profile = services.get_profile("ro-crate") +if not rocrate_profile: + raise RuntimeError("Unable to load the RO-Crate profile") +check_local_data_entity_existence = rocrate_profile.get_requirement_check( + "Web-based Data Entity: resource availability" +) +assert ( + check_local_data_entity_existence +), "Unable to find the requirement 'Web-based Data Entity: resource availability'" +SKIP_WEB_RESOURCE_AVAILABILITY_IDENTIFIER = check_local_data_entity_existence.identifier + def test_valid_five_safes_crate_request_required(): """Test a valid Five Safes Crate representing a request.""" @@ -36,6 +50,27 @@ def test_valid_five_safes_crate_request_required(): ) +@pytest.mark.xfail( + reason=""" + Checks that ensure certain Five Safes actions are present currently fail for this crate, + as this crate represents an early stage of a process before those actions have happened. + """ +) +def test_valid_five_safes_crate_request_recommended(): + """Test a valid Five Safes Crate representing a request.""" + do_entity_test( + ValidROC().five_safes_crate_request, + Severity.RECOMMENDED, + True, + profile_identifier="five-safes-crate", + skip_checks=[ + SKIP_LOCAL_DATA_ENTITY_EXISTENCE_CHECK_IDENTIFIER, + SKIP_WEB_RESOURCE_AVAILABILITY_IDENTIFIER, + ], + disable_inherited_profiles_reporting=True, + ) + + def test_valid_five_safes_crate_result_required(): """Test a valid Five Safes Crate representing a result.""" do_entity_test( @@ -49,6 +84,21 @@ def test_valid_five_safes_crate_result_required(): ) +def test_valid_five_safes_crate_result_recommended(): + """Test a valid Five Safes Crate representing a result.""" + do_entity_test( + ValidROC().five_safes_crate_result, + Severity.RECOMMENDED, + True, + profile_identifier="five-safes-crate", + skip_checks=[ + SKIP_LOCAL_DATA_ENTITY_EXISTENCE_CHECK_IDENTIFIER, + SKIP_WEB_RESOURCE_AVAILABILITY_IDENTIFIER, + ], + disable_inherited_profiles_reporting=True, + ) + + def test_valid_five_safes_crate_multiple_context(): """Test a valid Five Safes Crate representing a result.""" do_entity_test( From 0501f2ce1d9d5f5e5d4d9503c98391c2c4758cdf Mon Sep 17 00:00:00 2001 From: Eli Chadwick Date: Mon, 5 Jan 2026 13:39:00 +0000 Subject: [PATCH 5/5] add explanation for use of SKIP_WEB_RESOURCE_AVAILABILITY_IDENTIFIER --- tests/integration/profiles/five-safes-crate/test_valid_5src.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/integration/profiles/five-safes-crate/test_valid_5src.py b/tests/integration/profiles/five-safes-crate/test_valid_5src.py index 4bbbff2a..6a7754fd 100644 --- a/tests/integration/profiles/five-safes-crate/test_valid_5src.py +++ b/tests/integration/profiles/five-safes-crate/test_valid_5src.py @@ -25,6 +25,8 @@ logger.setLevel(logging.DEBUG) # Dynamically fetch the SKIP_WEB_RESOURCE_AVAILABILITY_IDENTIFIER +# required as disable_inherited_profiles_reporting does not disable Python checks from +# inherited profiles (https://github.com/crs4/rocrate-validator/issues/135) rocrate_profile = services.get_profile("ro-crate") if not rocrate_profile: raise RuntimeError("Unable to load the RO-Crate profile")