1616from rocrate_validator .models import ValidationContext
1717from rocrate_validator .requirements .python import (PyFunctionCheck , check ,
1818 requirement )
19+ from rocrate_validator .utils .uri import AvailabilityStatus
1920
2021# set up logging
2122logger = logging .getLogger (__name__ )
@@ -32,13 +33,37 @@ class WebDataEntityRecommendedChecker(PyFunctionCheck):
3233 def check_availability (self , context : ValidationContext ) -> bool :
3334 """
3435 Check if the Web-based Data Entity is directly downloadable
35- by a simple retrieval (e.g. HTTP GET) permitting redirection and HTTP/HTTPS URIs
36+ by a simple retrieval (e.g. HTTP GET) permitting redirection and HTTP/HTTPS URIs.
37+
38+ Resources that cannot be natively retrieved by the validator (e.g.
39+ `scp://`, `s3://`, `sftp://`) or that are protected by an authorization
40+ mechanism (HTTP 401/403) are reported as recommendation-level issues
41+ and logged as warnings, without invalidating the validation.
3642 """
3743 result = True
3844 for entity in context .ro_crate .metadata .get_web_data_entities ():
3945 assert entity .id is not None , "Entity has no @id"
4046 try :
41- if not entity .is_available ():
47+ status = entity .check_availability ()
48+ if status == AvailabilityStatus .AVAILABLE :
49+ continue
50+ if status == AvailabilityStatus .UNAUTHORIZED :
51+ msg = (
52+ f"Web-based Data Entity { entity .id } is protected by an "
53+ f"authorization mechanism; availability could not be verified"
54+ )
55+ logger .warning (msg )
56+ context .result .add_issue (msg , self )
57+ elif status == AvailabilityStatus .UNCHECKABLE :
58+ scheme = entity .id_as_uri .scheme
59+ msg = (
60+ f"Web-based Data Entity { entity .id } uses scheme "
61+ f"'{ scheme } ' which is not natively supported by the "
62+ f"validator; availability could not be verified"
63+ )
64+ logger .warning (msg )
65+ context .result .add_issue (msg , self )
66+ else :
4267 context .result .add_issue (
4368 f'Web-based Data Entity { entity .id } is not available' , self )
4469 result = False
@@ -59,6 +84,12 @@ def check_content_size(self, context: ValidationContext) -> bool:
5984 result = True
6085 for entity in context .ro_crate .metadata .get_web_data_entities ():
6186 assert entity .id is not None , "Entity has no @id"
87+ # Skip entities whose scheme the validator cannot natively fetch
88+ # (e.g. scp://, s3://): without retrieving the content there is
89+ # no actual size to compare `contentSize` against. Reachability
90+ # is then checked separately via `is_available()` below.
91+ if not entity .id_as_uri .is_natively_checkable ():
92+ continue
6293 if entity .is_available ():
6394 content_size = entity .get_property ("contentSize" )
6495 if content_size and int (content_size ) != context .ro_crate .get_external_file_size (entity .id ):
0 commit comments