Skip to content

Commit 079fed8

Browse files
authored
Merge pull request #74 from kikkomep/feat/improve-multiprofile-validation-output
feat: enhance JSON output for multi-profile validation
2 parents a830c06 + b55f598 commit 079fed8

File tree

10 files changed

+990
-19
lines changed

10 files changed

+990
-19
lines changed

rocrate_validator/cli/commands/validate.py

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
from __future__ import annotations
1616

17+
import json
1718
import os
1819
import sys
1920
from pathlib import Path
@@ -39,8 +40,8 @@
3940
from rocrate_validator.colors import get_severity_color
4041
from rocrate_validator.errors import ROCrateInvalidURIError
4142
from rocrate_validator.events import Event, EventType, Subscriber
42-
from rocrate_validator.models import (LevelCollection, Profile, Severity,
43-
ValidationResult)
43+
from rocrate_validator.models import (CustomEncoder, LevelCollection, Profile,
44+
Severity, ValidationResult)
4445
from rocrate_validator.utils import (URI, get_profiles_path,
4546
validate_rocrate_uri)
4647

@@ -355,6 +356,7 @@ def validate(ctx,
355356

356357
# Validate the RO-Crate against the selected profiles
357358
is_valid = True
359+
results = {}
358360
for profile in profile_identifier:
359361
# Set the selected profile
360362
validation_settings["profile_identifier"] = profile
@@ -382,6 +384,7 @@ def validate(ctx,
382384
result: ValidationResult = services.validate(
383385
validation_settings
384386
)
387+
results[profile] = result
385388

386389
# store the cumulative validation result
387390
is_valid = is_valid and result.passed(LevelCollection.get(requirement_severity).severity)
@@ -399,26 +402,45 @@ def validate(ctx,
399402
if verbose_choice == "y" or verbose:
400403
report_layout.show_validation_details(pager, enable_pager=enable_pager)
401404

402-
if output_format == "json" and not output_file:
403-
console.print(result.to_json())
404-
405-
if output_file:
406-
# Print the validation report to a file
407-
if output_format == "json":
408-
with open(output_file, "w") as f:
409-
f.write(result.to_json())
410-
elif output_format == "text":
411-
with open(output_file, "w") as f:
412-
c = Console(file=f, color_system=None, width=output_line_width, height=31)
413-
c.print(report_layout.layout)
414-
report_layout.console = c
415-
if not result.passed() and verbose:
416-
report_layout.show_validation_details(None, enable_pager=False)
405+
# Print the textual validation report to a file
406+
if output_file and output_format == "text":
407+
with open(output_file, "w") as f:
408+
c = Console(file=f, color_system=None, width=output_line_width, height=31)
409+
c.print(report_layout.layout)
410+
report_layout.console = c
411+
if not result.passed() and verbose:
412+
report_layout.show_validation_details(None, enable_pager=False)
417413

418414
# Interrupt the validation if the fail fast mode is enabled
419415
if fail_fast and not is_valid:
420416
break
421417

418+
# Process JSON output format
419+
if output_format == "json":
420+
# Init the JSON output
421+
json_output = results[profile_identifier[0]].to_dict()
422+
# Init issues list
423+
if not json_output.get("issues", None):
424+
json_output["issues"] = []
425+
# Always remove the property "profile identifier"
426+
json_output["validation_settings"].pop("profile_identifier")
427+
# Set the list of validation profiles
428+
json_output["validation_settings"]["profile_identifiers"] = profile_identifier
429+
# Set the list of validation profiles
430+
if len(results) > 1:
431+
for i in range(1, len(profile_identifier)):
432+
result_i: ValidationResult = results[profile_identifier[i]]
433+
json_output["passed"] = json_output["passed"] and result_i.passed()
434+
if result_i.has_issues():
435+
json_output["issues"].extend(result_i.to_dict().get("issues"))
436+
# Print the validation report to the console
437+
if not output_file:
438+
console.print(json.dumps(json_output, indent=4, cls=CustomEncoder))
439+
# Print the validation report to a file
440+
if output_file:
441+
with open(output_file, "w") as f:
442+
f.write(json.dumps(json_output, indent=4, cls=CustomEncoder))
443+
422444
# using ctx.exit seems to raise an Exception that gets caught below,
423445
# so we use sys.exit instead.
424446
sys.exit(0 if is_valid else 1)

rocrate_validator/constants.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@
8484
]
8585

8686
# Current JSON output format
87-
JSON_OUTPUT_FORMAT_VERSION = "0.1"
87+
JSON_OUTPUT_FORMAT_VERSION = "0.2"
8888

8989
# Default value for the HTTP cache timeout
9090
DEFAULT_HTTP_CACHE_TIMEOUT = 60
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
Call me Ishmael. Some years ago--never mind how long precisely--having
2+
little or no money in my purse, and nothing particular to interest me on
3+
shore, I thought I would sail about a little and see the watery part of
4+
the world. It is a way I have of driving off the spleen and regulating
5+
the circulation. Whenever I find myself growing grim about the mouth;
6+
whenever it is a damp, drizzly November in my soul; whenever I find
7+
myself involuntarily pausing before coffin warehouses, and bringing up
8+
the rear of every funeral I meet; and especially whenever my hypos get
9+
such an upper hand of me, that it requires a strong moral principle to
10+
prevent me from deliberately stepping into the street, and methodically
11+
knocking people's hats off--then, I account it high time to get to sea
12+
as soon as I can. This is my substitute for pistol and ball. With a
13+
philosophical flourish Cato throws himself upon his sword; I quietly
14+
take to the ship. There is nothing surprising in this. If they but knew
15+
it, almost all men in their degree, some time or other, cherish very
16+
nearly the same feelings towards the ocean with me.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
gnivah--ylesicerp gnol woh dnim reven--oga sraey emoS .leamhsI em llaC
2+
no em tseretni ot ralucitrap gnihton dna ,esrup ym ni yenom on ro elttil
3+
fo trap yretaw eht ees dna elttil a tuoba lias dluow I thguoht I ,erohs
4+
gnitaluger dna neelps eht ffo gnivird fo evah I yaw a si tI .dlrow eht
5+
;htuom eht tuoba mirg gniworg flesym dnif I revenehW .noitalucric eht
6+
dnif I revenehw ;luos ym ni rebmevoN ylzzird ,pmad a si ti revenehw
7+
pu gnignirb dna ,sesuoheraw niffoc erofeb gnisuap yliratnulovni flesym
8+
teg sopyh ym revenehw yllaicepse dna ;teem I larenuf yreve fo raer eht
9+
ot elpicnirp larom gnorts a seriuqer ti taht ,em fo dnah reppu na hcus
10+
yllacidohtem dna ,teerts eht otni gnippets yletarebiled morf em tneverp
11+
aes ot teg ot emit hgih ti tnuocca I ,neht--ffo stah s'elpoep gnikconk
12+
a htiW .llab dna lotsip rof etutitsbus ym si sihT .nac I sa noos sa
13+
ylteiuq I ;drows sih nopu flesmih sworht otaC hsiruolf lacihposolihp
14+
wenk tub yeht fI .siht ni gnisirprus gnihton si erehT .pihs eht ot ekat
15+
yrev hsirehc ,rehto ro emit emos ,eerged rieht ni nem lla tsomla ,ti
16+
.em htiw naeco eht sdrawot sgnileef emas eht ylraen
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
yrev hsirehc ,rehto ro emit emos ,eerged rieht ni nem lla tsomla ,ti
2+
ylteiuq I ;drows sih nopu flesmih sworht otaC hsiruolf lacihposolihp
3+
yllacidohtem dna ,teerts eht otni gnippets yletarebiled morf em tneverp
4+
wenk tub yeht fI .siht ni gnisirprus gnihton si erehT .pihs eht ot ekat
5+
teg sopyh ym revenehw yllaicepse dna ;teem I larenuf yreve fo raer eht
6+
pu gnignirb dna ,sesuoheraw niffoc erofeb gnisuap yliratnulovni flesym
7+
ot elpicnirp larom gnorts a seriuqer ti taht ,em fo dnah reppu na hcus
8+
no em tseretni ot ralucitrap gnihton dna ,esrup ym ni yenom on ro elttil
9+
gnivah--ylesicerp gnol woh dnim reven--oga sraey emoS .leamhsI em llaC
10+
gnitaluger dna neelps eht ffo gnivird fo evah I yaw a si tI .dlrow eht
11+
fo trap yretaw eht ees dna elttil a tuoba lias dluow I thguoht I ,erohs
12+
dnif I revenehw ;luos ym ni rebmevoN ylzzird ,pmad a si ti revenehw
13+
aes ot teg ot emit hgih ti tnuocca I ,neht--ffo stah s'elpoep gnikconk
14+
a htiW .llab dna lotsip rof etutitsbus ym si sihT .nac I sa noos sa
15+
;htuom eht tuoba mirg gniworg flesym dnif I revenehW .noitalucric eht
16+
.em htiw naeco eht sdrawot sgnileef emas eht ylraen
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
{
2+
"$graph": [
3+
{
4+
"class": "Workflow",
5+
"doc": "Reverse the lines in a document, then sort those lines.",
6+
"hints": [
7+
{
8+
"class": "DockerRequirement",
9+
"dockerPull": "debian:8"
10+
}
11+
],
12+
"inputs": [
13+
{
14+
"type": "File",
15+
"doc": "The input file to be processed.",
16+
"format": "https://www.iana.org/assignments/media-types/text/plain",
17+
"default": {
18+
"class": "File",
19+
"location": "file:///home/stain/src/cwltool/tests/wf/hello.txt"
20+
},
21+
"id": "#main/input"
22+
},
23+
{
24+
"type": "boolean",
25+
"default": true,
26+
"doc": "If true, reverse (decending) sort",
27+
"id": "#main/reverse_sort"
28+
}
29+
],
30+
"outputs": [
31+
{
32+
"type": "File",
33+
"outputSource": "#main/sorted/output",
34+
"doc": "The output with the lines reversed and sorted.",
35+
"id": "#main/output"
36+
}
37+
],
38+
"steps": [
39+
{
40+
"in": [
41+
{
42+
"source": "#main/input",
43+
"id": "#main/rev/input"
44+
}
45+
],
46+
"out": [
47+
"#main/rev/output"
48+
],
49+
"run": "#revtool.cwl",
50+
"id": "#main/rev"
51+
},
52+
{
53+
"in": [
54+
{
55+
"source": "#main/rev/output",
56+
"id": "#main/sorted/input"
57+
},
58+
{
59+
"source": "#main/reverse_sort",
60+
"id": "#main/sorted/reverse"
61+
}
62+
],
63+
"out": [
64+
"#main/sorted/output"
65+
],
66+
"run": "#sorttool.cwl",
67+
"id": "#main/sorted"
68+
}
69+
],
70+
"id": "#main",
71+
"$namespaces": {
72+
"iana": "https://www.iana.org/assignments/media-types/"
73+
}
74+
},
75+
{
76+
"class": "CommandLineTool",
77+
"doc": "Reverse each line using the `rev` command",
78+
"inputs": [
79+
{
80+
"type": "File",
81+
"inputBinding": {},
82+
"id": "#revtool.cwl/input"
83+
}
84+
],
85+
"outputs": [
86+
{
87+
"type": "File",
88+
"outputBinding": {
89+
"glob": "output.txt"
90+
},
91+
"id": "#revtool.cwl/output"
92+
}
93+
],
94+
"baseCommand": "rev",
95+
"stdout": "output.txt",
96+
"id": "#revtool.cwl"
97+
},
98+
{
99+
"class": "CommandLineTool",
100+
"doc": "Sort lines using the `sort` command",
101+
"inputs": [
102+
{
103+
"id": "#sorttool.cwl/reverse",
104+
"type": "boolean",
105+
"inputBinding": {
106+
"position": 1,
107+
"prefix": "--reverse"
108+
}
109+
},
110+
{
111+
"id": "#sorttool.cwl/input",
112+
"type": "File",
113+
"inputBinding": {
114+
"position": 2
115+
}
116+
}
117+
],
118+
"outputs": [
119+
{
120+
"id": "#sorttool.cwl/output",
121+
"type": "File",
122+
"outputBinding": {
123+
"glob": "output.txt"
124+
}
125+
}
126+
],
127+
"baseCommand": "sort",
128+
"stdout": "output.txt",
129+
"id": "#sorttool.cwl"
130+
}
131+
],
132+
"cwlVersion": "v1.0",
133+
"$schemas": [
134+
"file:///home/stain/src/cwltool/tests/wf/empty.ttl",
135+
"file:///home/stain/src/cwltool/tests/wf/empty2.ttl"
136+
]
137+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"input": {
3+
"class": "File",
4+
"location": "327fc7aedf4f6b69a42a7c8b808dc5a7aff61376",
5+
"format": "https://www.iana.org/assignments/media-types/text/plain",
6+
"size": 1111,
7+
"basename": "whale.txt",
8+
"nameroot": "whale",
9+
"nameext": ".txt",
10+
"checksum": "sha1$327fc7aedf4f6b69a42a7c8b808dc5a7aff61376"
11+
},
12+
"reverse_sort": true
13+
}

0 commit comments

Comments
 (0)