ftr_ruby 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +5 -0
- data/LICENSE.txt +21 -0
- data/Rakefile +12 -0
- data/doc/CHANGELOG_md.html +526 -0
- data/doc/FtrRuby/DCAT_Record.html +1324 -0
- data/doc/FtrRuby/Error.html +606 -0
- data/doc/FtrRuby/FDPIndex.html +966 -0
- data/doc/FtrRuby/Output.html +1355 -0
- data/doc/FtrRuby/TestInfra.html +713 -0
- data/doc/FtrRuby/Tests.html +690 -0
- data/doc/FtrRuby.html +588 -0
- data/doc/Gemfile.html +548 -0
- data/doc/Gemfile_lock.html +1074 -0
- data/doc/LICENSE_txt.html +527 -0
- data/doc/OpenAPI.html +1103 -0
- data/doc/README_md.html +716 -0
- data/doc/Rakefile.html +529 -0
- data/doc/bin/setup.html +523 -0
- data/doc/created.rid +19 -0
- data/doc/css/rdoc.css +1955 -0
- data/doc/index.html +518 -0
- data/doc/js/aliki.js +511 -0
- data/doc/js/bash_highlighter.js +167 -0
- data/doc/js/c_highlighter.js +299 -0
- data/doc/js/search_controller.js +129 -0
- data/doc/js/search_data.js +1 -0
- data/doc/js/search_navigation.js +105 -0
- data/doc/js/search_ranker.js +239 -0
- data/doc/js/theme-toggle.js +112 -0
- data/doc/sig/ftr_ruby_rbs.html +524 -0
- data/lib/dcat_metadata.rb +232 -0
- data/lib/fdp_index.rb +168 -0
- data/lib/ftr_ruby/version.rb +5 -0
- data/lib/ftr_ruby.rb +28 -0
- data/lib/openapi.rb +79 -0
- data/lib/output.rb +181 -0
- data/lib/registertest.rb +23 -0
- data/lib/test_infrastructure.rb +53 -0
- data/sig/ftr_ruby.rbs +4 -0
- metadata +85 -0
data/lib/output.rb
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
module FtrRuby
|
|
2
|
+
##
|
|
3
|
+
# Represents the output/result of executing a FAIR test against a specific resource.
|
|
4
|
+
#
|
|
5
|
+
# This class generates a provenance-rich RDF graph describing a single test execution,
|
|
6
|
+
# including the result score, log messages, summary, and optional guidance for improvement.
|
|
7
|
+
#
|
|
8
|
+
# The output follows the FAIR Test Registry (FTR) vocabulary and uses PROV for tracing
|
|
9
|
+
# the execution activity and the tested entity.
|
|
10
|
+
#
|
|
11
|
+
# @example
|
|
12
|
+
# output = FtrRuby::Output.new(
|
|
13
|
+
# testedGUID: "https://doi.org/10.5281/zenodo.1234567",
|
|
14
|
+
# meta: test_meta_hash
|
|
15
|
+
# )
|
|
16
|
+
# output.score = "pass"
|
|
17
|
+
# output.comments << "Resource has a resolvable persistent identifier."
|
|
18
|
+
# jsonld = output.createEvaluationResponse
|
|
19
|
+
#
|
|
20
|
+
class Output
|
|
21
|
+
include TripleEasy # get the :"triplify" function
|
|
22
|
+
# triplify(s, p, o, repo, datatype: nil, context: nil, language: 'en')
|
|
23
|
+
include RDF
|
|
24
|
+
|
|
25
|
+
attr_accessor :score, :testedGUID, :testid, :uniqueid, :name, :description, :license, :dt, :metric, :softwareid,
|
|
26
|
+
:version, :summary, :completeness, :comments, :guidance, :creator, :protocol, :host, :basePath, :api
|
|
27
|
+
|
|
28
|
+
OPUTPUT_VERSION = "1.1.1"
|
|
29
|
+
|
|
30
|
+
##
|
|
31
|
+
# Creates a new test output instance.
|
|
32
|
+
#
|
|
33
|
+
# @param testedGUID [String] The identifier (usually URI) of the resource being tested
|
|
34
|
+
# @param meta [Hash] Metadata about the test (same structure used by DCAT_Record)
|
|
35
|
+
#
|
|
36
|
+
def initialize(testedGUID:, meta:)
|
|
37
|
+
@score = "indeterminate"
|
|
38
|
+
@testedGUID = testedGUID
|
|
39
|
+
@uniqueid = "urn:fairtestoutput:" + SecureRandom.uuid
|
|
40
|
+
@name = meta[:testname]
|
|
41
|
+
@description = meta[:description]
|
|
42
|
+
@license = meta[:license] || "https://creativecommons.org/licenses/by/4.0/"
|
|
43
|
+
@dt = Time.now.iso8601
|
|
44
|
+
@metric = meta[:metric]
|
|
45
|
+
@version = meta[:testversion]
|
|
46
|
+
@summary = meta[:summary] || "Summary:"
|
|
47
|
+
@completeness = "100"
|
|
48
|
+
@comments = []
|
|
49
|
+
@guidance = meta.fetch(:guidance, [])
|
|
50
|
+
@creator = meta[:creator]
|
|
51
|
+
@protocol = meta[:protocol].gsub(%r{[:/]}, "")
|
|
52
|
+
@host = meta[:host].gsub(%r{[:/]}, "")
|
|
53
|
+
@basePath = meta[:basePath].gsub(%r{[:/]}, "")
|
|
54
|
+
@softwareid = "#{@protocol}://#{@host}/#{@basePath}/#{meta[:testid]}"
|
|
55
|
+
@api = "#{@softwareid}/api"
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
##
|
|
59
|
+
# Generates the full evaluation response as JSON-LD.
|
|
60
|
+
#
|
|
61
|
+
# Builds an RDF graph containing:
|
|
62
|
+
# * A `ftr:TestExecutionActivity`
|
|
63
|
+
# * A `ftr:TestResult` with score, summary, log, and guidance
|
|
64
|
+
# * Links to the tested entity and the test software
|
|
65
|
+
# * Provenance information
|
|
66
|
+
#
|
|
67
|
+
# @return [String] JSON-LD representation of the test result graph
|
|
68
|
+
#
|
|
69
|
+
def createEvaluationResponse
|
|
70
|
+
g = RDF::Graph.new
|
|
71
|
+
schema = RDF::Vocab::SCHEMA
|
|
72
|
+
xsd = RDF::Vocab::XSD
|
|
73
|
+
dct = RDF::Vocab::DC
|
|
74
|
+
prov = RDF::Vocab::PROV
|
|
75
|
+
dcat = RDF::Vocab::DCAT
|
|
76
|
+
dqv = RDF::Vocabulary.new("https://www.w3.org/TR/vocab-dqv/")
|
|
77
|
+
ftr = RDF::Vocabulary.new("https://w3id.org/ftr#")
|
|
78
|
+
sio = RDF::Vocabulary.new("http://semanticscience.org/resource/")
|
|
79
|
+
cwmo = RDF::Vocabulary.new("http://purl.org/cwmo/#")
|
|
80
|
+
|
|
81
|
+
add_newline_to_comments
|
|
82
|
+
|
|
83
|
+
if summary =~ /^Summary$/
|
|
84
|
+
summary = "Summary of test results: #{comments[-1]}"
|
|
85
|
+
summary ||= "Summary of test results: #{comments[-2]}"
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
executionid = "urn:ostrails:testexecutionactivity:" + SecureRandom.uuid
|
|
89
|
+
|
|
90
|
+
# tid = 'urn:ostrails:fairtestentity:' + SecureRandom.uuid
|
|
91
|
+
# The entity is no longer an anonymous node, it is the GUID Of the tested input
|
|
92
|
+
|
|
93
|
+
triplify(executionid, RDF.type, ftr.TestExecutionActivity, g)
|
|
94
|
+
triplify(executionid, prov.wasAssociatedWith, softwareid, g)
|
|
95
|
+
triplify(uniqueid, prov.wasGeneratedBy, executionid, g)
|
|
96
|
+
|
|
97
|
+
triplify(uniqueid, RDF.type, ftr.TestResult, g)
|
|
98
|
+
triplify(uniqueid, dct.identifier, uniqueid.to_s, g, datatype: xsd.string)
|
|
99
|
+
triplify(uniqueid, dct.title, "#{name} OUTPUT", g)
|
|
100
|
+
triplify(uniqueid, dct.description, "OUTPUT OF #{description}", g)
|
|
101
|
+
triplify(uniqueid, dct.license, license, g)
|
|
102
|
+
triplify(uniqueid, prov.value, score, g)
|
|
103
|
+
triplify(uniqueid, ftr.summary, summary, g)
|
|
104
|
+
triplify(uniqueid, RDF::Vocab::PROV.generatedAtTime, dt, g)
|
|
105
|
+
triplify(uniqueid, ftr.log, comments.join, g)
|
|
106
|
+
triplify(uniqueid, ftr.completion, completeness, g)
|
|
107
|
+
|
|
108
|
+
triplify(uniqueid, ftr.outputFromTest, softwareid, g)
|
|
109
|
+
triplify(softwareid, RDF.type, ftr.Test, g)
|
|
110
|
+
triplify(softwareid, RDF.type, schema.SoftwareApplication, g)
|
|
111
|
+
triplify(softwareid, RDF.type, dcat.DataService, g)
|
|
112
|
+
triplify(softwareid, dct.identifier, softwareid.to_s, g, datatype: xsd.string)
|
|
113
|
+
triplify(softwareid, dct.title, "#{name}", g)
|
|
114
|
+
triplify(softwareid, dct.description, description, g)
|
|
115
|
+
triplify(softwareid, dcat.endpointDescription, api, g) # returns yaml
|
|
116
|
+
triplify(softwareid, dcat.endpointURL, softwareid, g) # POST to execute
|
|
117
|
+
triplify(softwareid, "http://www.w3.org/ns/dcat#version", "#{version} OutputVersion:#{OPUTPUT_VERSION}", g) # dcat namespace in library has no version - dcat 2 not 3
|
|
118
|
+
triplify(softwareid, dct.license, "https://github.com/wilkinsonlab/FAIR-Core-Tests/blob/main/LICENSE", g)
|
|
119
|
+
triplify(softwareid, sio["SIO_000233"], metric, g) # implementation of
|
|
120
|
+
|
|
121
|
+
# deprecated after release 1.0
|
|
122
|
+
# triplify(uniqueid, prov.wasDerivedFrom, tid, g)
|
|
123
|
+
# triplify(executionid, prov.used, tid, g)
|
|
124
|
+
# triplify(tid, RDF.type, prov.Entity, g)
|
|
125
|
+
# triplify(tid, schema.identifier, testedGUID, g, xsd.string)
|
|
126
|
+
# triplify(tid, schema.url, testedGUID, g) if testedGUID =~ %r{^https?://}
|
|
127
|
+
testedguidnode = "urn:ostrails:testedidentifiernode:" + SecureRandom.uuid
|
|
128
|
+
|
|
129
|
+
begin
|
|
130
|
+
triplify(uniqueid, ftr.assessmentTarget, testedguidnode, g)
|
|
131
|
+
triplify(executionid, prov.used, testedguidnode, g)
|
|
132
|
+
triplify(testedguidnode, RDF.type, prov.Entity, g)
|
|
133
|
+
triplify(testedguidnode, dct.identifier, testedGUID, g, datatype: xsd.string)
|
|
134
|
+
rescue StandardError
|
|
135
|
+
triplify(uniqueid, ftr.assessmentTarget, "not a URI", g)
|
|
136
|
+
triplify(executionid, prov.used, "not a URI", g)
|
|
137
|
+
score = "fail"
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
unless score == "pass"
|
|
141
|
+
guidance.each do |advice, label|
|
|
142
|
+
adviceid = "urn:ostrails:testexecutionactivity:advice:" + SecureRandom.uuid
|
|
143
|
+
triplify(uniqueid, ftr.suggestion, adviceid, g)
|
|
144
|
+
triplify(adviceid, RDF.type, ftr.GuidanceContext, g)
|
|
145
|
+
triplify(adviceid, RDFS.label, label, g)
|
|
146
|
+
triplify(adviceid, dct.description, label, g)
|
|
147
|
+
triplify(adviceid, sio["SIO_000339"], RDF::URI.new(advice), g)
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# g.dump(:jsonld)
|
|
152
|
+
w = RDF::Writer.for(:jsonld)
|
|
153
|
+
w.dump(g, nil, prefixes: {
|
|
154
|
+
xsd: RDF::Vocab::XSD,
|
|
155
|
+
prov: RDF::Vocab::PROV,
|
|
156
|
+
dct: RDF::Vocab::DC,
|
|
157
|
+
dcat: RDF::Vocab::DCAT,
|
|
158
|
+
ftr: ftr,
|
|
159
|
+
sio: sio,
|
|
160
|
+
schema: schema
|
|
161
|
+
})
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
class << self
|
|
165
|
+
attr_reader :comments
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def self.clear_comments
|
|
169
|
+
@comments = []
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def add_newline_to_comments
|
|
173
|
+
cleancomments = []
|
|
174
|
+
@comments.each do |c|
|
|
175
|
+
c += "\n" unless c =~ /\n$/
|
|
176
|
+
cleancomments << c
|
|
177
|
+
end
|
|
178
|
+
@comments = cleancomments
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
end
|
data/lib/registertest.rb
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
require "rest-client"
|
|
2
|
+
module FtrRuby
|
|
3
|
+
class Tests
|
|
4
|
+
def self.register_test(test_uri:, proxy_url: "https://tools.ostrails.eu/fdp-index-proxy/proxy")
|
|
5
|
+
warn "registering new test"
|
|
6
|
+
# curl -v -L -H "content-type: application/json"
|
|
7
|
+
# -d '{"clientUrl": "https://my.domain.org/path/to/DCAT/testdcat.ttl"}'
|
|
8
|
+
# https://tools.ostrails.eu/fdp-index-proxy/proxy
|
|
9
|
+
begin
|
|
10
|
+
response = RestClient::Request.execute({
|
|
11
|
+
method: :post,
|
|
12
|
+
url: proxy_url,
|
|
13
|
+
headers: { "Accept" => "application/json",
|
|
14
|
+
"Content-Type" => "application/json" },
|
|
15
|
+
payload: { "clientUrl": test_uri }.to_json
|
|
16
|
+
}).body
|
|
17
|
+
rescue StandardError => e
|
|
18
|
+
warn "response is #{response.inspect} error #{e.inspect}"
|
|
19
|
+
end
|
|
20
|
+
response
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
module FtrRuby
|
|
2
|
+
class TestInfra
|
|
3
|
+
attr_accessor :test_protocol, :test_host, :basepath
|
|
4
|
+
|
|
5
|
+
def initialize(test_host:, basepath:, test_protocol:)
|
|
6
|
+
@test_host = test_host
|
|
7
|
+
@test_protocol = test_protocol
|
|
8
|
+
@basepath = basepath
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# there is a need to map between a test and its registered Metric in FS. This will return the label for the test
|
|
12
|
+
# in principle, we cojuld return a more complex object, but all I need now is the label
|
|
13
|
+
def get_tests_metrics(tests:)
|
|
14
|
+
labels = {}
|
|
15
|
+
landingpages = {}
|
|
16
|
+
tests.each do |testid|
|
|
17
|
+
warn "getting dcat for #{testid} #{test_protocol}://#{test_host}/#{basepath}/#{testid}"
|
|
18
|
+
dcat = RestClient::Request.execute({
|
|
19
|
+
method: :get,
|
|
20
|
+
url: "#{test_protocol}://#{test_host}/#{basepath}/#{testid}",
|
|
21
|
+
headers: { "Accept" => "application/json" }
|
|
22
|
+
}).body
|
|
23
|
+
parseddcat = JSON.parse(dcat)
|
|
24
|
+
# this next line should probably be done with SPARQL
|
|
25
|
+
# # TODO TODO TODO
|
|
26
|
+
jpath = JsonPath.new('[0]["http://semanticscience.org/resource/SIO_000233"][0]["@id"]') # is implementation of
|
|
27
|
+
metricurl = jpath.on(parseddcat).first
|
|
28
|
+
|
|
29
|
+
begin
|
|
30
|
+
g = RDF::Graph.load(metricurl, format: :turtle)
|
|
31
|
+
rescue StandardError => e
|
|
32
|
+
warn "DCAT Metric loading failed #{e.inspect}"
|
|
33
|
+
g = RDF::Graph.new
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
title = g.query([nil, RDF::Vocab::DC.title, nil])&.first&.object&.to_s
|
|
37
|
+
lp = g.query([nil, RDF::Vocab::DCAT.landingPage, nil])&.first&.object&.to_s
|
|
38
|
+
|
|
39
|
+
labels[testid] = if title != ""
|
|
40
|
+
title
|
|
41
|
+
else
|
|
42
|
+
"Metric label not available"
|
|
43
|
+
end
|
|
44
|
+
landingpages[testid] = if lp != ""
|
|
45
|
+
lp
|
|
46
|
+
else
|
|
47
|
+
""
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
[labels, landingpages]
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
data/sig/ftr_ruby.rbs
ADDED
metadata
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: ftr_ruby
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.4
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- markwilkinson
|
|
8
|
+
bindir: exe
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies: []
|
|
12
|
+
description: Libraries supporting the FAIR Testing Resources Vocabulary - Tests and
|
|
13
|
+
test outputs.
|
|
14
|
+
email:
|
|
15
|
+
- mark.wilkinson@upm.es
|
|
16
|
+
executables: []
|
|
17
|
+
extensions: []
|
|
18
|
+
extra_rdoc_files: []
|
|
19
|
+
files:
|
|
20
|
+
- CHANGELOG.md
|
|
21
|
+
- LICENSE.txt
|
|
22
|
+
- Rakefile
|
|
23
|
+
- doc/CHANGELOG_md.html
|
|
24
|
+
- doc/FtrRuby.html
|
|
25
|
+
- doc/FtrRuby/DCAT_Record.html
|
|
26
|
+
- doc/FtrRuby/Error.html
|
|
27
|
+
- doc/FtrRuby/FDPIndex.html
|
|
28
|
+
- doc/FtrRuby/Output.html
|
|
29
|
+
- doc/FtrRuby/TestInfra.html
|
|
30
|
+
- doc/FtrRuby/Tests.html
|
|
31
|
+
- doc/Gemfile.html
|
|
32
|
+
- doc/Gemfile_lock.html
|
|
33
|
+
- doc/LICENSE_txt.html
|
|
34
|
+
- doc/OpenAPI.html
|
|
35
|
+
- doc/README_md.html
|
|
36
|
+
- doc/Rakefile.html
|
|
37
|
+
- doc/bin/setup.html
|
|
38
|
+
- doc/created.rid
|
|
39
|
+
- doc/css/rdoc.css
|
|
40
|
+
- doc/index.html
|
|
41
|
+
- doc/js/aliki.js
|
|
42
|
+
- doc/js/bash_highlighter.js
|
|
43
|
+
- doc/js/c_highlighter.js
|
|
44
|
+
- doc/js/search_controller.js
|
|
45
|
+
- doc/js/search_data.js
|
|
46
|
+
- doc/js/search_navigation.js
|
|
47
|
+
- doc/js/search_ranker.js
|
|
48
|
+
- doc/js/theme-toggle.js
|
|
49
|
+
- doc/sig/ftr_ruby_rbs.html
|
|
50
|
+
- lib/dcat_metadata.rb
|
|
51
|
+
- lib/fdp_index.rb
|
|
52
|
+
- lib/ftr_ruby.rb
|
|
53
|
+
- lib/ftr_ruby/version.rb
|
|
54
|
+
- lib/openapi.rb
|
|
55
|
+
- lib/output.rb
|
|
56
|
+
- lib/registertest.rb
|
|
57
|
+
- lib/test_infrastructure.rb
|
|
58
|
+
- sig/ftr_ruby.rbs
|
|
59
|
+
homepage: https://github.com/markwilkinson/FTR-Ruby/tree/master
|
|
60
|
+
licenses:
|
|
61
|
+
- MIT
|
|
62
|
+
metadata:
|
|
63
|
+
allowed_push_host: https://rubygems.org
|
|
64
|
+
homepage_uri: https://github.com/markwilkinson/FTR-Ruby/tree/master
|
|
65
|
+
source_code_uri: https://github.com/markwilkinson/FTR-Ruby/tree/master
|
|
66
|
+
documentation_uri: https://rubydoc.info/gems/ftr_ruby
|
|
67
|
+
bug_tracker_uri: https://github.com/markwilkinson/FTR-Ruby/issues
|
|
68
|
+
rdoc_options: []
|
|
69
|
+
require_paths:
|
|
70
|
+
- lib
|
|
71
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - ">="
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: 3.2.0
|
|
76
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
77
|
+
requirements:
|
|
78
|
+
- - ">="
|
|
79
|
+
- !ruby/object:Gem::Version
|
|
80
|
+
version: '0'
|
|
81
|
+
requirements: []
|
|
82
|
+
rubygems_version: 4.0.9
|
|
83
|
+
specification_version: 4
|
|
84
|
+
summary: Libraries supporting the FTR Vocabulary.
|
|
85
|
+
test_files: []
|