Skip to content

Commit fcd6ff1

Browse files
authored
Merge pull request #113 from crs4/develop
Merge updates from upstream
2 parents cd58c3c + 3252731 commit fcd6ff1

81 files changed

Lines changed: 7573 additions & 1149 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/release.yaml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ jobs:
9292
- name: 🏗️ Build a binary wheel and a source tarball
9393
run: poetry build
9494
- name: 📦 Store the distribution packages
95-
uses: actions/upload-artifact@v4
95+
uses: actions/upload-artifact@v7
9696
with:
9797
name: python-package-distributions
9898
path: |
@@ -111,7 +111,7 @@ jobs:
111111
id-token: write # IMPORTANT: mandatory for trusted publishing
112112
steps:
113113
- name: ⬇️ Download all the distribution packages
114-
uses: actions/download-artifact@v4
114+
uses: actions/download-artifact@v8
115115
with:
116116
name: python-package-distributions
117117
path: dist/
@@ -132,7 +132,7 @@ jobs:
132132
id-token: write # IMPORTANT: mandatory for trusted publishing
133133
steps:
134134
- name: ⬇️ Download all the dists
135-
uses: actions/download-artifact@v4
135+
uses: actions/download-artifact@v8
136136
with:
137137
name: python-package-distributions
138138
path: dist/
@@ -151,18 +151,18 @@ jobs:
151151

152152
steps:
153153
- name: ⬇️ Download all the distribution packages
154-
uses: actions/download-artifact@v4
154+
uses: actions/download-artifact@v8
155155
with:
156156
name: python-package-distributions
157157
path: dist/
158158
- name: 🖊️ Sign the dists with Sigstore
159-
uses: sigstore/gh-action-sigstore-python@v3.0.0
159+
uses: sigstore/gh-action-sigstore-python@v3.3.0
160160
with:
161161
inputs: >-
162162
./dist/*.tar.gz
163163
./dist/*.whl
164164
- name: 📦 Store the signed distribution packages
165-
uses: actions/upload-artifact@v4
165+
uses: actions/upload-artifact@v7
166166
with:
167167
name: python-package-signatures
168168
path: dist/*.json
@@ -177,12 +177,12 @@ jobs:
177177
id-token: write # IMPORTANT: mandatory for sigstore
178178
steps:
179179
- name: ⬇️ Download all the distribution packages
180-
uses: actions/download-artifact@v4
180+
uses: actions/download-artifact@v8
181181
with:
182182
name: python-package-distributions
183183
path: dist/
184184
- name: ⬇️ Download all the distribution signatures
185-
uses: actions/download-artifact@v4
185+
uses: actions/download-artifact@v8
186186
with:
187187
name: python-package-signatures
188188
path: dist/

.github/workflows/testing.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ jobs:
5656
- name: ⌛ Lint Python code
5757
run: flake8 -v rocrate_validator tests
5858
- name: ⌛ Spell check code and profiles (covers Python and SHACL)
59-
uses: crate-ci/typos@v1.41.0
59+
uses: crate-ci/typos@v1.47.0
6060

6161
# Runs the tests
6262
test:

CHANGELOG.md

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,85 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [0.10.0] - 2026-06-01
9+
10+
Full changelog: https://github.com/crs4/rocrate-validator/compare/0.9.0...0.10.0
11+
12+
### ✨ Added
13+
14+
- feat(cli): add offline mode with an `--offline` flag and an HTTP `cache` subcommand to validate RO-Crates without network access ([e296f10](https://github.com/crs4/rocrate-validator/commit/e296f10), [f8b99bc](https://github.com/crs4/rocrate-validator/commit/f8b99bc))
15+
- feat(utils): add a cache-aware JSON-LD document loader and HTTP cache warm-up from profile artifacts ([eedabf1](https://github.com/crs4/rocrate-validator/commit/eedabf1), [949ec6f](https://github.com/crs4/rocrate-validator/commit/949ec6f))
16+
- feat(utils): add offline mode and cache management to `HttpRequester`, with configurable cache path ([c92d88c](https://github.com/crs4/rocrate-validator/commit/c92d88c), [7c9e825](https://github.com/crs4/rocrate-validator/commit/7c9e825))
17+
- feat(core): support offline mode when downloading remote RO-Crates ([57eceb5](https://github.com/crs4/rocrate-validator/commit/57eceb5))
18+
- feat(cli/cache): add `cache list` (alias `ls`) and allow caching of explicit URLs via `cache warm` ([f9b43ae](https://github.com/crs4/rocrate-validator/commit/f9b43ae), [6925d55](https://github.com/crs4/rocrate-validator/commit/6925d55))
19+
- feat(cli): extend the `describe` command to describe individual requirement checks ([f3fb7f3](https://github.com/crs4/rocrate-validator/commit/f3fb7f3))
20+
- feat(model): add a `SourceSnippet` class and `RequirementCheck.get_source_snippet`, implemented for both SHACL and Python checks ([9f48674](https://github.com/crs4/rocrate-validator/commit/9f48674), [25bc7b4](https://github.com/crs4/rocrate-validator/commit/25bc7b4), [fe740e4](https://github.com/crs4/rocrate-validator/commit/fe740e4))
21+
- feat(checks): support a `deactivated` flag on `RequirementCheck` to override/deactivate checks by name for Python and SHACL ([dd84c32](https://github.com/crs4/rocrate-validator/commit/dd84c32), [4196f0e](https://github.com/crs4/rocrate-validator/commit/4196f0e))
22+
- feat(rocrate): add `check_availability()` with `AvailabilityStatus` on entities and granular remote-scheme classification ([76e92a4](https://github.com/crs4/rocrate-validator/commit/76e92a4), [469bbe5](https://github.com/crs4/rocrate-validator/commit/469bbe5))
23+
- feat(checks): handle `UNAUTHORIZED`/`UNCHECKABLE` web data entities as warnings ([0196dc9](https://github.com/crs4/rocrate-validator/commit/0196dc9))
24+
- feat(uri): add an `is_external_reference()` scheme detector ([62f89c0](https://github.com/crs4/rocrate-validator/commit/62f89c0))
25+
- feat(model): extend the `Profile` model to compute descendants ([a9783ce](https://github.com/crs4/rocrate-validator/commit/a9783ce))
26+
- ISA profile: add RDF classes for ISA types and a dedicated `Process` class for process checks ([3ff4245](https://github.com/crs4/rocrate-validator/commit/3ff4245), [e3fda59](https://github.com/crs4/rocrate-validator/commit/e3fda59), [c3e2d5f](https://github.com/crs4/rocrate-validator/commit/c3e2d5f))
27+
28+
### 🔧 Changed
29+
30+
- refactor(models): introduce pre/post internal validation hooks on `Validator` ([e43364b](https://github.com/crs4/rocrate-validator/commit/e43364b))
31+
- refactor(SHACL): rewrite `build_node_subgraph` as an iterative BNode traversal ([23164b7](https://github.com/crs4/rocrate-validator/commit/23164b7))
32+
- refactor(errors): accept `str`, `Path` or `URI` in `ROCrateInvalidURIError` ([0b8289b](https://github.com/crs4/rocrate-validator/commit/0b8289b))
33+
- refactor(cli/cache): drop the `Status` column from the `cache list` table ([392df1a](https://github.com/crs4/rocrate-validator/commit/392df1a))
34+
- feat(constants): default the HTTP cache to never expire ([419fece](https://github.com/crs4/rocrate-validator/commit/419fece))
35+
36+
### 🐛 Fixed
37+
38+
- fix(shacl): build property shape subgraphs by reachability and derive `NodeShape` level from nested `PropertyShape`s ([f1c0cfd](https://github.com/crs4/rocrate-validator/commit/f1c0cfd), [50448145](https://github.com/crs4/rocrate-validator/commit/5044814))
39+
- fix(shacl): evaluate inherited shapes for zero-shape target profiles ([bcb5cac](https://github.com/crs4/rocrate-validator/commit/bcb5cac))
40+
- fix(shacl): drop sub-threshold PySHACL violations at the source ([254fb88](https://github.com/crs4/rocrate-validator/commit/254fb88))
41+
- fix(core): filter failed requirements/checks by the configured severity ([a306f7f](https://github.com/crs4/rocrate-validator/commit/a306f7f))
42+
- fix(models): forward `extra_profiles_path` when computing validation statistics ([7b3e8bc](https://github.com/crs4/rocrate-validator/commit/7b3e8bc))
43+
- fix(uri): treat `file://` URIs with a non-local authority as remote ([63acb6a](https://github.com/crs4/rocrate-validator/commit/63acb6a))
44+
- fix(cli/cache): resolve profile tokens in `cache warm` and avoid `stream=True` when fetching remote crates ([7926832](https://github.com/crs4/rocrate-validator/commit/7926832), [33012b6](https://github.com/crs4/rocrate-validator/commit/33012b6))
45+
- fix(validation): report offline cache misses once per URL ([757b86a](https://github.com/crs4/rocrate-validator/commit/757b86a))
46+
- fix(ISA): correct the error message for a bad position in `HowToStep` ([03a32fc](https://github.com/crs4/rocrate-validator/commit/03a32fc))
47+
48+
### 📚 Documentation
49+
50+
- docs: add a dedicated documentation page for the cache and offline mode features ([e10c3b5](https://github.com/crs4/rocrate-validator/commit/e10c3b5))
51+
- docs(profiles): document check override-by-name and deactivation ([0b6bff7](https://github.com/crs4/rocrate-validator/commit/0b6bff7))
52+
53+
## [0.9.0] - 2026-04-20
54+
55+
Full changelog: https://github.com/crs4/rocrate-validator/compare/0.8.1...0.9.0
56+
57+
### ✨ Added
58+
59+
- feat(profiles/isa): add the ISA RO-Crate profile, with checks and tests for Investigation, Study, Assay, Process, Protocol, Sample, Data, Person and PropertyValue entities ([852fb23](https://github.com/crs4/rocrate-validator/commit/852fb23), [d62e214](https://github.com/crs4/rocrate-validator/commit/d62e214), [727b6f0](https://github.com/crs4/rocrate-validator/commit/727b6f0))
60+
- feat(cli): add CLI options to configure the HTTP cache (`--cache-path`, `--cache-max-age`) ([564230f](https://github.com/crs4/rocrate-validator/commit/564230f))
61+
- feat(model): enable cache configuration in `ValidationSettings` ([b2b47ba](https://github.com/crs4/rocrate-validator/commit/b2b47ba))
62+
- feat(utils): extend the `HttpRequester` constructor to support cache configuration parameters ([2f2a873](https://github.com/crs4/rocrate-validator/commit/2f2a873))
63+
- feat(ro-crate): refine the constraint enforcing metadata descriptor existence ([2c6ea76](https://github.com/crs4/rocrate-validator/commit/2c6ea76))
64+
- feat(file-descriptor): add an internal remote-context retrieval method supporting the alternate `Link` header ([f8b0e55](https://github.com/crs4/rocrate-validator/commit/f8b0e55))
65+
66+
### 🔧 Changed
67+
68+
- refactor(ro-crate): relax the `ROCrateMetadataFileDescriptor` class definition ([61ddbb5](https://github.com/crs4/rocrate-validator/commit/61ddbb5))
69+
- refactor(file-descriptor): route checks through the new remote-context retrieval method ([0ce2619](https://github.com/crs4/rocrate-validator/commit/0ce2619))
70+
- chore(utils): increase the session cache max age to 300 seconds ([36ca0ac](https://github.com/crs4/rocrate-validator/commit/36ca0ac))
71+
- ci(gh-actions): update outdated GitHub Actions ([d565c5d](https://github.com/crs4/rocrate-validator/commit/d565c5d))
72+
73+
### 🐛 Fixed
74+
75+
- fix(ro-crate): target metadata descriptor shapes by class and select the candidate descriptor via SPARQL ([8219f27](https://github.com/crs4/rocrate-validator/commit/8219f27), [39bd761](https://github.com/crs4/rocrate-validator/commit/39bd761), [1a91aa4](https://github.com/crs4/rocrate-validator/commit/1a91aa4))
76+
- fix(shacl): extract `@base` from the JSON-LD document for ontology parsing ([57f5c54](https://github.com/crs4/rocrate-validator/commit/57f5c54))
77+
- fix(SHACL-core): improve SHACL violation parsing with better error handling ([90a9f06](https://github.com/crs4/rocrate-validator/commit/90a9f06))
78+
- fix(file-descriptor): accept `application/json` and treat the `Link` header case-insensitively for remote context retrieval ([fe5ba1c](https://github.com/crs4/rocrate-validator/commit/fe5ba1c))
79+
- fix(file-descriptor): refine the compacted JSON-LD key validation logic ([45a7017](https://github.com/crs4/rocrate-validator/commit/45a7017))
80+
- fix(core): allow terms defined by context prefixes ([5fe8171](https://github.com/crs4/rocrate-validator/commit/5fe8171))
81+
- fix(core): fix output formatting ([523fbf4](https://github.com/crs4/rocrate-validator/commit/523fbf4))
82+
83+
### 📚 Documentation
84+
85+
- docs(cli): document the `-1` value for no cache expiration in the `--cache-max-age` help ([c5848bc](https://github.com/crs4/rocrate-validator/commit/c5848bc))
86+
887
## [0.8.1] - 2026-02-18
988

1089
Full changelog: https://github.com/crs4/rocrate-validator/compare/0.8.0...0.8.1

docs/0_toc.rst

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
..
2-
Copyright (c) 2024 CRS4
2+
Copyright (c) 2024-2026 CRS4
33
44
Licensed under the Apache License, Version 2.0 (the "License");
55
you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@
2121
2_usage_cli
2222
3_usage_api
2323
4_how_it_works
24+
5_offline_mode
2425

2526
.. toctree::
2627
:maxdepth: 5
@@ -30,3 +31,9 @@
3031
11_writing_a_profile
3132
10_api
3233
genindex
34+
35+
.. toctree::
36+
:maxdepth: 1
37+
:caption: About
38+
39+
ack

docs/10_api.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
..
2-
Copyright (c) 2024 CRS4
2+
Copyright (c) 2024-2026 CRS4
33
44
Licensed under the Apache License, Version 2.0 (the "License");
55
you may not use this file except in compliance with the License.
@@ -135,7 +135,7 @@ Python Check API
135135
======================
136136

137137
Requirement Class
138-
----------
138+
-----------------
139139
.. autoclass:: rocrate_validator.requirements.python.PyRequirement
140140
:members:
141141

docs/11_writing_a_profile.rst

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,154 @@ These instructions assume you are familiar with code development using Python an
9494
#. When your profile & tests are written, open a pull request to contribute
9595
it back to the repository!
9696

97+
Overriding inherited checks
98+
---------------------------
99+
100+
When a profile inherits from another profile (via ``prof:isProfileOf`` /
101+
``prof:isTransitiveProfileOf``), it automatically receives every check
102+
declared by its ancestors. The validator additionally supports
103+
**override-by-name**: a child profile can replace an inherited check by
104+
declaring a new check with the **same name**.
105+
106+
This allows an extension profile to *redefine* the content of an inherited
107+
check — for example, to make a constraint stricter or looser, change its
108+
severity, or, as described in the next section, fully deactivate it.
109+
110+
Override-by-name is enabled by default. It can be disabled via the
111+
``allow_requirement_check_override`` validation setting (CLI / API), which
112+
will raise an error on duplicate check names instead.
113+
114+
SHACL checks
115+
^^^^^^^^^^^^
116+
117+
Each SHACL ``NodeShape`` / ``PropertyShape`` becomes a check whose name is
118+
its ``sh:name``. To override an inherited check, declare a shape in the
119+
extension profile with the **same** ``sh:name`` as the inherited one:
120+
121+
.. code-block:: turtle
122+
123+
# Parent profile
124+
ro:ShapeC
125+
a sh:NodeShape ;
126+
sh:name "The Shape C" ;
127+
sh:targetNode ro:ro-crate-metadata.json ;
128+
sh:property [
129+
a sh:PropertyShape ;
130+
sh:name "Check Metadata File Descriptor entity existence" ;
131+
sh:path rdf:type ;
132+
sh:minCount 1 ;
133+
sh:message "Missing entity" ;
134+
] .
135+
136+
.. code-block:: turtle
137+
138+
# Extension profile — overrides the inherited PropertyShape by sh:name
139+
ro:ShapeC
140+
a sh:NodeShape ;
141+
sh:name "The Shape C" ;
142+
sh:targetNode ro:ro-crate-metadata.json ;
143+
sh:property [
144+
a sh:PropertyShape ;
145+
sh:name "Check Metadata File Descriptor entity existence" ;
146+
sh:path rdf:type ;
147+
sh:minCount 1 ;
148+
sh:maxCount 1 ;
149+
sh:message "Stricter override from extension profile" ;
150+
] .
151+
152+
Both top-level shapes and ``PropertyShape`` entries nested inside a parent
153+
``NodeShape`` (i.e., declared inline, without an absolute IRI) can be
154+
overridden this way.
155+
156+
Python checks
157+
^^^^^^^^^^^^^
158+
159+
Python checks declared via the ``@check`` decorator are matched by their
160+
``name`` argument. To override an inherited Python check, declare a new
161+
function with the same ``name`` in the extension profile:
162+
163+
.. code-block:: python
164+
165+
# In the extension profile's checks module
166+
from rocrate_validator.requirements.python import check
167+
168+
@check(name="Check Metadata File Descriptor entity existence")
169+
def overridden_check(self, ctx):
170+
# New implementation that replaces the inherited one
171+
...
172+
173+
Deactivating inherited checks
174+
-----------------------------
175+
176+
A child profile can also **fully deactivate** a check inherited from one of
177+
its ancestors. A deactivated check is skipped during validation and
178+
reported as such in the validation result. This is useful when an extension
179+
profile relaxes the parent's expectations, or replaces a coarse-grained
180+
check with a more specific one declared elsewhere in the same profile.
181+
182+
SHACL checks
183+
^^^^^^^^^^^^
184+
185+
Two complementary mechanisms are supported, depending on whether the shape
186+
to disable has an absolute IRI of its own.
187+
188+
**Shape with an absolute IRI** (e.g. a top-level ``NodeShape`` or a named
189+
``PropertyShape``): reference the shape by IRI from the extension profile
190+
and mark it as deactivated, without redeclaring it.
191+
192+
.. code-block:: turtle
193+
194+
# Extension profile
195+
<https://parent-profile/ShapeC> sh:deactivated true .
196+
197+
**Nested ``PropertyShape`` without an absolute IRI** (a property declared
198+
inline inside a parent ``NodeShape``): use the override-by-name mechanism
199+
described in the previous section. Declare a new ``PropertyShape`` in the
200+
extension profile with the same ``sh:name`` as the one to disable, and set
201+
``sh:deactivated true`` on it. This overrides the parent's
202+
``PropertyShape``, and the validator reports the resulting check as
203+
deactivated.
204+
205+
.. code-block:: turtle
206+
207+
# Extension profile — disables the inherited PropertyShape by sh:name
208+
ro:ShapeC
209+
a sh:NodeShape ;
210+
sh:name "The Shape C" ;
211+
sh:targetNode ro:ro-crate-metadata.json ;
212+
sh:property [
213+
a sh:PropertyShape ;
214+
sh:name "Check Metadata File Descriptor entity existence" ;
215+
sh:path rdf:type ;
216+
sh:deactivated true ;
217+
] .
218+
219+
.. note::
220+
221+
Cross-profile deactivation is scoped to the shape's transitive
222+
descendants: a ``sh:deactivated true`` triple declared by a profile
223+
that does not inherit (directly or transitively) from the shape's
224+
owning profile is ignored. This prevents unrelated profiles loaded in
225+
the same process from interfering with one another.
226+
227+
Python checks
228+
^^^^^^^^^^^^^
229+
230+
The ``@check`` decorator accepts a ``deactivated`` flag, mirroring SHACL's
231+
``sh:deactivated``. Combined with override-by-name, an extension profile
232+
can disable an inherited Python check by redeclaring it with
233+
``deactivated=True``:
234+
235+
.. code-block:: python
236+
237+
from rocrate_validator.requirements.python import check
238+
239+
@check(name="Check Metadata File Descriptor entity existence",
240+
deactivated=True)
241+
def disabled(self, ctx):
242+
# Body is irrelevant — the check is skipped during validation.
243+
return True
244+
97245
Running validator & tests during profile development
98246
----------------------------------------------------
99247

docs/1_installation.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
..
2-
Copyright (c) 2024 CRS4
2+
Copyright (c) 2024-2026 CRS4
33
44
Licensed under the Apache License, Version 2.0 (the "License");
55
you may not use this file except in compliance with the License.

docs/2_usage_cli.rst

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
..
2-
Copyright (c) 2024 CRS4
2+
Copyright (c) 2024-2026 CRS4
33
44
Licensed under the Apache License, Version 2.0 (the "License");
55
you may not use this file except in compliance with the License.
@@ -31,3 +31,9 @@ CLI Validation
3131
:parser: myst_parser.sphinx_
3232
:start-line: 93
3333
:end-line: 120
34+
35+
.. seealso::
36+
37+
To validate without network access and manage the HTTP cache from the
38+
command line (the ``--offline`` and ``--no-cache`` flags and the ``cache``
39+
subcommand), see :ref:`offline_mode`.

docs/3_usage_api.rst

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
..
2-
Copyright (c) 2024 CRS4
2+
Copyright (c) 2024-2026 CRS4
33
44
Licensed under the Apache License, Version 2.0 (the "License");
55
you may not use this file except in compliance with the License.
@@ -30,6 +30,12 @@ Programmatic Validation
3030
:start-line: 121
3131
:end-line: 162
3232

33+
.. seealso::
34+
35+
To resolve resources from a local cache or run validation without network
36+
access (the ``offline`` / ``no_cache`` settings of ``ValidationSettings``),
37+
see :ref:`offline_mode`.
38+
3339

3440
Metadata-only Validation
3541
------------------------

0 commit comments

Comments
 (0)