ro-crate 0.5.1 → 0.5.2
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 +4 -4
- data/.gitignore +2 -0
- data/lib/ro_crate/json_ld_hash.rb +0 -5
- data/lib/ro_crate/model/directory.rb +1 -1
- data/lib/ro_crate/model/exceptions/exception.rb +15 -0
- data/lib/ro_crate/model/exceptions/read_exception.rb +4 -0
- data/lib/ro_crate/reader.rb +20 -14
- data/lib/ro_crate/ro-crate-preview.html.erb +3 -2
- data/lib/ro_crate.rb +2 -0
- data/ro_crate.gemspec +1 -1
- data/test/entity_test.rb +17 -0
- data/test/entry_test.rb +110 -0
- data/test/fixtures/arcp/ro-crate-metadata.json +21 -0
- data/test/fixtures/broken/missing_file/file2.txt +1 -0
- data/test/fixtures/broken/missing_file/ro-crate-metadata.json +32 -0
- data/test/fixtures/broken/no_graph/ro-crate-metadata.json +3 -0
- data/test/fixtures/broken/no_metadata_entity/ro-crate-metadata.json +6 -0
- data/test/fixtures/broken/no_metadata_file/test.txt +1 -0
- data/test/fixtures/broken/no_root_entity/ro-crate-metadata.json +12 -0
- data/test/fixtures/broken/not_json/ro-crate-metadata.json +9 -0
- data/test/fixtures/dir_symlink +1 -0
- data/test/fixtures/symlink +1 -0
- data/test/reader_test.rb +78 -0
- data/test/writer_test.rb +40 -28
- metadata +15 -3
- data/Gemfile.lock +0 -50
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f2462dcf00e2593cf8ea7108af9f9b6ef54ef773aea01be125f7c79ce67c2850
|
4
|
+
data.tar.gz: 40955bc76cd0344b80b727a79f5888ddc99d3874ecf3f8ce4db64ac2a722d713
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7bd16f57d802a39d378cbcfa663ecc55acfbc77256013a50d7490a652cf383186c99dbbd0c28d5747751c33aa79fe06033e1a90a15cb6f2052139045992afc76
|
7
|
+
data.tar.gz: 8a6f755b6fa96e511ca1ff4c034f049c6148acd2fe4f1aa8e7a71ab231217dd2dfc4fdde7cc92cae0d6ab1d077aa36f2d13afe98ee7fbecfe0ccd532a0580325
|
data/.gitignore
CHANGED
@@ -2,11 +2,6 @@ module ROCrate
|
|
2
2
|
##
|
3
3
|
# A wrapper class for Hash that adds methods to dereference Entities within an RO-Crate.
|
4
4
|
class JSONLDHash < ::Hash
|
5
|
-
def self.[](graph, content = {})
|
6
|
-
@graph = graph
|
7
|
-
super(stringified(content))
|
8
|
-
end
|
9
|
-
|
10
5
|
def initialize(graph, content = {})
|
11
6
|
@graph = graph
|
12
7
|
super()
|
@@ -59,7 +59,7 @@ module ROCrate
|
|
59
59
|
# @return [Hash{String => Entry}>] The files/directories that were populated.
|
60
60
|
# The key is the relative path of the file/directory, and the value is an Entry object where data can be read etc.
|
61
61
|
def populate_entries(source_directory, include_hidden: false)
|
62
|
-
raise 'Not a directory' unless ::File.directory?(source_directory)
|
62
|
+
raise TypeError, 'Not a directory' unless ::File.directory?(source_directory)
|
63
63
|
@directory_entries = {}
|
64
64
|
list_all_files(source_directory, include_hidden: include_hidden).each do |rel_path|
|
65
65
|
source_path = Pathname.new(::File.join(source_directory, rel_path)).expand_path
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module ROCrate
|
2
|
+
class Exception < StandardError
|
3
|
+
attr_reader :inner_exception
|
4
|
+
|
5
|
+
def initialize(message, _inner_exception = nil)
|
6
|
+
if _inner_exception
|
7
|
+
@inner_exception = _inner_exception
|
8
|
+
super("#{message}: #{@inner_exception.class.name} - #{@inner_exception.message}")
|
9
|
+
set_backtrace(@inner_exception.backtrace)
|
10
|
+
else
|
11
|
+
super(message)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/ro_crate/reader.rb
CHANGED
@@ -9,7 +9,6 @@ module ROCrate
|
|
9
9
|
# @param target_dir [String, ::File, Pathname] The target directory where the crate should be unzipped (if its a Zip file).
|
10
10
|
# @return [Crate] The RO-Crate.
|
11
11
|
def self.read(source, target_dir: Dir.mktmpdir)
|
12
|
-
raise "Not a directory!" unless ::File.directory?(target_dir)
|
13
12
|
begin
|
14
13
|
is_dir = ::File.directory?(source)
|
15
14
|
rescue TypeError
|
@@ -82,6 +81,8 @@ module ROCrate
|
|
82
81
|
# @param target_dir [String, ::File, Pathname] The target directory where the crate should be unzipped.
|
83
82
|
# @return [Crate] The RO-Crate.
|
84
83
|
def self.read_zip(source, target_dir: Dir.mktmpdir)
|
84
|
+
raise ROCrate::ReadException, "Target is not a directory!" unless ::File.directory?(target_dir)
|
85
|
+
|
85
86
|
unzip_to(source, target_dir)
|
86
87
|
|
87
88
|
# Traverse the unzipped directory to try and find the crate's root
|
@@ -96,7 +97,7 @@ module ROCrate
|
|
96
97
|
# @param source [String, ::File, Pathname] The location of the directory.
|
97
98
|
# @return [Crate] The RO-Crate.
|
98
99
|
def self.read_directory(source)
|
99
|
-
raise "
|
100
|
+
raise ROCrate::ReadException, "Source is not a directory!" unless ::File.directory?(source)
|
100
101
|
|
101
102
|
source = ::File.expand_path(source)
|
102
103
|
metadata_file = Dir.entries(source).detect { |entry| entry == ROCrate::Metadata::IDENTIFIER ||
|
@@ -104,13 +105,18 @@ module ROCrate
|
|
104
105
|
|
105
106
|
if metadata_file
|
106
107
|
metadata_json = ::File.read(::File.join(source, metadata_file))
|
107
|
-
|
108
|
+
begin
|
109
|
+
metadata = JSON.parse(metadata_json)
|
110
|
+
rescue JSON::ParserError => e
|
111
|
+
raise ROCrate::ReadException.new("Error parsing metadata", e)
|
112
|
+
end
|
113
|
+
|
108
114
|
entities = entities_from_metadata(metadata)
|
109
115
|
context = metadata['@context']
|
110
116
|
|
111
117
|
build_crate(entities, source, context: context)
|
112
118
|
else
|
113
|
-
raise
|
119
|
+
raise ROCrate::ReadException, "No metadata found!"
|
114
120
|
end
|
115
121
|
end
|
116
122
|
|
@@ -131,14 +137,14 @@ module ROCrate
|
|
131
137
|
|
132
138
|
# Do some normalization...
|
133
139
|
entities[ROCrate::Metadata::IDENTIFIER] = extract_metadata_entity(entities)
|
134
|
-
raise "No metadata entity found in @graph!" unless entities[ROCrate::Metadata::IDENTIFIER]
|
140
|
+
raise ROCrate::ReadException, "No metadata entity found in @graph!" unless entities[ROCrate::Metadata::IDENTIFIER]
|
135
141
|
entities[ROCrate::Preview::IDENTIFIER] = extract_preview_entity(entities)
|
136
142
|
entities[ROCrate::Crate::IDENTIFIER] = extract_root_entity(entities)
|
137
|
-
raise "No root entity (with @id: #{entities[ROCrate::Metadata::IDENTIFIER].dig('about', '@id')}) found in @graph!" unless entities[ROCrate::Crate::IDENTIFIER]
|
143
|
+
raise ROCrate::ReadException, "No root entity (with @id: #{entities[ROCrate::Metadata::IDENTIFIER].dig('about', '@id')}) found in @graph!" unless entities[ROCrate::Crate::IDENTIFIER]
|
138
144
|
|
139
145
|
entities
|
140
146
|
else
|
141
|
-
raise "No @graph found in metadata!"
|
147
|
+
raise ROCrate::ReadException, "No @graph found in metadata!"
|
142
148
|
end
|
143
149
|
end
|
144
150
|
|
@@ -198,7 +204,7 @@ module ROCrate
|
|
198
204
|
# @param entity_hash [Hash] A Hash containing all the entities in the @graph, mapped by their @id.
|
199
205
|
# @return [Array<ROCrate::File, ROCrate::Directory>] The extracted DataEntity objects.
|
200
206
|
def self.extract_data_entities(crate, source, entity_hash)
|
201
|
-
crate.raw_properties['hasPart'].map do |ref|
|
207
|
+
(crate.raw_properties['hasPart'] || []).map do |ref|
|
202
208
|
entity_props = entity_hash.delete(ref['@id'])
|
203
209
|
next unless entity_props
|
204
210
|
entity_class = ROCrate::DataEntity.specialize(entity_props)
|
@@ -234,21 +240,21 @@ module ROCrate
|
|
234
240
|
# or nil if it referenced a local file that wasn't found.
|
235
241
|
def self.create_data_entity(crate, entity_class, source, entity_props)
|
236
242
|
id = entity_props.delete('@id')
|
243
|
+
raise ROCrate::ReadException, "Data Entity missing '@id': #{entity_props.inspect}" unless id
|
237
244
|
decoded_id = URI.decode_www_form_component(id)
|
238
245
|
path = nil
|
239
246
|
uri = URI(id) rescue nil
|
240
247
|
if uri&.absolute?
|
241
248
|
path = uri
|
242
249
|
decoded_id = nil
|
243
|
-
|
250
|
+
elsif !id.start_with?('#')
|
244
251
|
[id, decoded_id].each do |i|
|
245
252
|
fullpath = ::File.join(source, i)
|
246
253
|
path = Pathname.new(fullpath) if ::File.exist?(fullpath)
|
247
254
|
end
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
# end
|
255
|
+
if path.nil?
|
256
|
+
raise ROCrate::ReadException, "Local Data Entity not found in crate: #{id}"
|
257
|
+
end
|
252
258
|
end
|
253
259
|
|
254
260
|
entity_class.new(crate, path, decoded_id, entity_props)
|
@@ -290,7 +296,7 @@ module ROCrate
|
|
290
296
|
# mapped by its @id.
|
291
297
|
def self.extract_root_entity(entities)
|
292
298
|
root_id = entities[ROCrate::Metadata::IDENTIFIER].dig('about', '@id')
|
293
|
-
raise "Metadata entity does not reference any root entity" unless root_id
|
299
|
+
raise ROCrate::ReadException, "Metadata entity does not reference any root entity" unless root_id
|
294
300
|
entities.delete(root_id)
|
295
301
|
end
|
296
302
|
|
@@ -1,10 +1,11 @@
|
|
1
1
|
<!DOCTYPE html>
|
2
|
-
<html>
|
2
|
+
<html lang="en">
|
3
3
|
<head>
|
4
4
|
<title><%= name || "New RO-Crate" %></title>
|
5
5
|
<script type="application/ld+json"><%= metadata.generate %></script>
|
6
|
-
<meta name="generator" content="https://github.com/
|
6
|
+
<meta name="generator" content="https://github.com/ResearchObject/ro-crate-ruby">
|
7
7
|
<meta name="keywords" content="RO-Crate">
|
8
|
+
<meta charset="utf-8">
|
8
9
|
</head>
|
9
10
|
<body>
|
10
11
|
<h1><%= name || "New RO-Crate" %></h1>
|
data/lib/ro_crate.rb
CHANGED
@@ -6,6 +6,8 @@ require 'zip/filesystem'
|
|
6
6
|
require 'addressable'
|
7
7
|
require 'open-uri'
|
8
8
|
|
9
|
+
require 'ro_crate/model/exceptions/exception'
|
10
|
+
require 'ro_crate/model/exceptions/read_exception'
|
9
11
|
require 'ro_crate/json_ld_hash'
|
10
12
|
require 'ro_crate/model/entity'
|
11
13
|
require 'ro_crate/model/data_entity'
|
data/ro_crate.gemspec
CHANGED
data/test/entity_test.rb
CHANGED
@@ -72,6 +72,23 @@ class EntityTest < Test::Unit::TestCase
|
|
72
72
|
assert_equal(person.canonical_id, crate.author.canonical_id)
|
73
73
|
end
|
74
74
|
|
75
|
+
test 'to_json' do
|
76
|
+
crate = ROCrate::Crate.new
|
77
|
+
|
78
|
+
crate['test'] = 'hello'
|
79
|
+
crate['test2'] = ['hello']
|
80
|
+
crate['test3'] = 123
|
81
|
+
crate['test4'] = { a: 'bc' }
|
82
|
+
|
83
|
+
json = crate.to_json
|
84
|
+
parsed = JSON.parse(json)
|
85
|
+
|
86
|
+
assert_equal 'hello', parsed['test']
|
87
|
+
assert_equal ['hello'], parsed['test2']
|
88
|
+
assert_equal 123, parsed['test3']
|
89
|
+
assert_equal({ 'a' => 'bc' }, parsed['test4'])
|
90
|
+
end
|
91
|
+
|
75
92
|
test 'format various IDs' do
|
76
93
|
assert_equal "#Hello%20World/Goodbye%20World", ROCrate::ContextualEntity.format_id('#Hello World/Goodbye World')
|
77
94
|
assert_equal "#Hello%20World/Goodbye%20World", ROCrate::ContextualEntity.format_id('Hello World/Goodbye World')
|
data/test/entry_test.rb
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'test_helper'
|
3
|
+
|
4
|
+
class EntryTest < Test::Unit::TestCase
|
5
|
+
setup do
|
6
|
+
stub_request(:get, 'http://example.com/dir/file.txt').to_return(status: 200, body: 'file contents')
|
7
|
+
stub_request(:get, 'http://example.com/dir/').to_return(status: 200, body: '<html>...')
|
8
|
+
|
9
|
+
@local_file = ROCrate::Entry.new(fixture_file('info.txt'))
|
10
|
+
@local_path = ROCrate::Entry.new(Pathname.new(fixture_dir).join('directory', 'info.txt'))
|
11
|
+
@local_io = ROCrate::Entry.new(StringIO.new('stringio'))
|
12
|
+
@local_dir = ROCrate::Entry.new(Pathname.new(fixture_dir).join('directory'))
|
13
|
+
@local_symlink = ROCrate::Entry.new(Pathname.new(fixture_dir).join('symlink'))
|
14
|
+
@local_dir_symlink = ROCrate::Entry.new(Pathname.new(fixture_dir).join('dir_symlink'))
|
15
|
+
@remote_file = ROCrate::RemoteEntry.new(URI('http://example.com/dir/file.txt'))
|
16
|
+
@remote_dir = ROCrate::RemoteEntry.new(URI('http://example.com/dir/'), directory: true)
|
17
|
+
end
|
18
|
+
|
19
|
+
test 'read' do
|
20
|
+
assert_equal "Hello\n", @local_file.read
|
21
|
+
assert_equal "1234\n", @local_path.read
|
22
|
+
assert_equal "stringio", @local_io.read
|
23
|
+
assert_raises(Errno::EISDIR) { @local_dir.read }
|
24
|
+
assert_raises(Errno::EISDIR) { @local_dir_symlink.read }
|
25
|
+
assert_equal "I have spaces in my name\n", @local_symlink.read
|
26
|
+
assert_equal "file contents", @remote_file.read
|
27
|
+
assert_equal "<html>...", @remote_dir.read
|
28
|
+
end
|
29
|
+
|
30
|
+
test 'write_to' do
|
31
|
+
dest = StringIO.new
|
32
|
+
@local_file.write_to(dest)
|
33
|
+
dest.rewind
|
34
|
+
assert_equal "Hello\n", dest.read
|
35
|
+
|
36
|
+
dest = StringIO.new
|
37
|
+
@local_path.write_to(dest)
|
38
|
+
dest.rewind
|
39
|
+
assert_equal "1234\n", dest.read
|
40
|
+
|
41
|
+
dest = StringIO.new
|
42
|
+
@local_io.write_to(dest)
|
43
|
+
dest.rewind
|
44
|
+
assert_equal "stringio", dest.read
|
45
|
+
|
46
|
+
assert_raises(Errno::EISDIR) { @local_dir.write_to(dest) }
|
47
|
+
|
48
|
+
assert_raises(Errno::EISDIR) { @local_dir_symlink.write_to(dest) }
|
49
|
+
|
50
|
+
dest = StringIO.new
|
51
|
+
@local_symlink.write_to(dest)
|
52
|
+
dest.rewind
|
53
|
+
assert_equal "I have spaces in my name\n", dest.read
|
54
|
+
|
55
|
+
dest = StringIO.new
|
56
|
+
@remote_file.write_to(dest)
|
57
|
+
dest.rewind
|
58
|
+
assert_equal "file contents", dest.read
|
59
|
+
|
60
|
+
dest = StringIO.new
|
61
|
+
@remote_dir.write_to(dest)
|
62
|
+
dest.rewind
|
63
|
+
assert_equal "<html>...", dest.read
|
64
|
+
end
|
65
|
+
|
66
|
+
test 'directory?' do
|
67
|
+
refute @local_file.directory?
|
68
|
+
refute @local_path.directory?
|
69
|
+
refute @local_io.directory?
|
70
|
+
assert @local_dir.directory?
|
71
|
+
refute @local_symlink.directory?
|
72
|
+
assert @local_dir_symlink.directory?
|
73
|
+
refute @remote_file.directory?
|
74
|
+
assert @remote_dir.directory?
|
75
|
+
end
|
76
|
+
|
77
|
+
test 'symlink?' do
|
78
|
+
refute @local_file.symlink?
|
79
|
+
refute @local_path.symlink?
|
80
|
+
refute @local_io.symlink?
|
81
|
+
refute @local_dir.symlink?
|
82
|
+
assert @local_symlink.symlink?
|
83
|
+
assert @local_dir_symlink.symlink?
|
84
|
+
refute @remote_file.symlink?
|
85
|
+
refute @remote_dir.symlink?
|
86
|
+
end
|
87
|
+
|
88
|
+
test 'remote?' do
|
89
|
+
refute @local_file.remote?
|
90
|
+
refute @local_path.remote?
|
91
|
+
refute @local_io.remote?
|
92
|
+
refute @local_dir.remote?
|
93
|
+
refute @local_symlink.remote?
|
94
|
+
refute @local_dir_symlink.remote?
|
95
|
+
assert @remote_file.remote?
|
96
|
+
assert @remote_dir.remote?
|
97
|
+
end
|
98
|
+
|
99
|
+
test 'path' do
|
100
|
+
base = Pathname.new(fixture_dir).expand_path.to_s
|
101
|
+
assert_equal "#{base}/info.txt", @local_file.path
|
102
|
+
assert_equal "#{base}/directory/info.txt", @local_path.path
|
103
|
+
assert_nil @local_io.path
|
104
|
+
assert_equal "#{base}/directory", @local_dir.path
|
105
|
+
assert_equal "#{base}/symlink", @local_symlink.path
|
106
|
+
assert_equal "#{base}/dir_symlink", @local_dir_symlink.path
|
107
|
+
assert_nil @remote_file.path
|
108
|
+
assert_nil @remote_dir.path
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
{
|
2
|
+
"@context": "https://w3id.org/ro/crate/1.1/context",
|
3
|
+
"@graph": [
|
4
|
+
{
|
5
|
+
"@id": "arcp://name,somethingsomething",
|
6
|
+
"@type": "Dataset",
|
7
|
+
"datePublished": "2024-01-31T10:47:17+00:00"
|
8
|
+
|
9
|
+
},
|
10
|
+
{
|
11
|
+
"@id": "ro-crate-metadata.json",
|
12
|
+
"@type": "CreativeWork",
|
13
|
+
"about": {
|
14
|
+
"@id": "arcp://name,somethingsomething"
|
15
|
+
},
|
16
|
+
"conformsTo": {
|
17
|
+
"@id": "https://w3id.org/ro/crate/1.1"
|
18
|
+
}
|
19
|
+
}
|
20
|
+
]
|
21
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
2
|
@@ -0,0 +1,32 @@
|
|
1
|
+
{
|
2
|
+
"@context": "https://w3id.org/ro/crate/1.1/context",
|
3
|
+
"@graph": [
|
4
|
+
{
|
5
|
+
"@id": "ro-crate-metadata.json",
|
6
|
+
"@type": "CreativeWork",
|
7
|
+
"about": {
|
8
|
+
"@id": "./"
|
9
|
+
}
|
10
|
+
},
|
11
|
+
{
|
12
|
+
"@id": "./",
|
13
|
+
"@type": "Dataset",
|
14
|
+
"hasPart": [
|
15
|
+
{
|
16
|
+
"@id": "file1.txt"
|
17
|
+
},
|
18
|
+
{
|
19
|
+
"@id": "file2.txt"
|
20
|
+
}
|
21
|
+
]
|
22
|
+
},
|
23
|
+
{
|
24
|
+
"@id": "file1.txt",
|
25
|
+
"@type": "File"
|
26
|
+
},
|
27
|
+
{
|
28
|
+
"@id": "file2.txt",
|
29
|
+
"@type": "File"
|
30
|
+
}
|
31
|
+
]
|
32
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
123
|
@@ -0,0 +1 @@
|
|
1
|
+
directory
|
@@ -0,0 +1 @@
|
|
1
|
+
file with spaces.txt
|
data/test/reader_test.rb
CHANGED
@@ -116,6 +116,19 @@ class ReaderTest < Test::Unit::TestCase
|
|
116
116
|
end
|
117
117
|
end
|
118
118
|
|
119
|
+
test 'reading from zip IO' do
|
120
|
+
io = StringIO.new(fixture_file('directory.zip').read)
|
121
|
+
crate = ROCrate::Reader.read(io)
|
122
|
+
|
123
|
+
assert crate.payload['fish/info.txt']
|
124
|
+
assert_equal '1234', crate.payload['fish/info.txt'].source.read.chomp
|
125
|
+
assert crate.payload['fish/root.txt']
|
126
|
+
assert crate.payload['fish/data/info.txt']
|
127
|
+
assert crate.payload['fish/data/nested.txt']
|
128
|
+
assert crate.payload['fish/data/binary.jpg']
|
129
|
+
assert_equal ['./', 'fish/', 'ro-crate-metadata.jsonld', 'ro-crate-preview.html'], crate.entities.map(&:id).sort
|
130
|
+
end
|
131
|
+
|
119
132
|
test 'reading from directory with directories' do
|
120
133
|
crate = ROCrate::Reader.read_directory(fixture_file('directory_crate').path)
|
121
134
|
|
@@ -303,4 +316,69 @@ class ReaderTest < Test::Unit::TestCase
|
|
303
316
|
refute real_file.payload.values.first.remote?
|
304
317
|
refute real_file.payload.values.first.directory?
|
305
318
|
end
|
319
|
+
|
320
|
+
test 'handles exceptions' do
|
321
|
+
e = check_exception(ROCrate::ReadException) do
|
322
|
+
ROCrate::Reader.read(fixture_file('broken/no_graph'))
|
323
|
+
end
|
324
|
+
assert_include e.message, 'No @graph'
|
325
|
+
|
326
|
+
e = check_exception(ROCrate::ReadException) do
|
327
|
+
ROCrate::Reader.read(fixture_file('broken/no_metadata_entity'))
|
328
|
+
end
|
329
|
+
assert_include e.message, 'No metadata entity'
|
330
|
+
|
331
|
+
e = check_exception(ROCrate::ReadException) do
|
332
|
+
ROCrate::Reader.read(fixture_file('broken/no_metadata_file'))
|
333
|
+
end
|
334
|
+
assert_include e.message, 'No metadata found'
|
335
|
+
|
336
|
+
e = check_exception(ROCrate::ReadException) do
|
337
|
+
ROCrate::Reader.read(fixture_file('broken/no_root_entity'))
|
338
|
+
end
|
339
|
+
assert_include e.message, 'No root'
|
340
|
+
|
341
|
+
e = check_exception(ROCrate::ReadException) do
|
342
|
+
ROCrate::Reader.read(fixture_file('broken/not_json'))
|
343
|
+
end
|
344
|
+
assert_include e.message, 'Error parsing metadata: JSON::ParserError'
|
345
|
+
assert_equal JSON::ParserError, e.inner_exception.class
|
346
|
+
|
347
|
+
e = check_exception(ROCrate::ReadException) do
|
348
|
+
ROCrate::Reader.read(fixture_file('workflow-0.2.0.zip'), target_dir: fixture_file('workflow-0.2.0.zip'))
|
349
|
+
end
|
350
|
+
assert_include e.message, 'Target is not a directory!'
|
351
|
+
|
352
|
+
e = check_exception(ROCrate::ReadException) do
|
353
|
+
ROCrate::Reader.read_directory(fixture_file('workflow-0.2.0.zip'))
|
354
|
+
end
|
355
|
+
assert_include e.message, 'Source is not a directory!'
|
356
|
+
|
357
|
+
e = check_exception(ROCrate::ReadException) do
|
358
|
+
ROCrate::Reader.read(fixture_file('broken/missing_file'))
|
359
|
+
end
|
360
|
+
assert_include e.message, 'not found in crate: file1.txt'
|
361
|
+
end
|
362
|
+
|
363
|
+
test 'tolerates arcp identifier on root data entity (and missing hasPart)' do
|
364
|
+
crate = ROCrate::Reader.read(fixture_file('arcp').path)
|
365
|
+
|
366
|
+
assert_equal 'arcp://name,somethingsomething', crate.id
|
367
|
+
assert_empty crate.data_entities
|
368
|
+
end
|
369
|
+
|
370
|
+
private
|
371
|
+
|
372
|
+
def check_exception(exception_class)
|
373
|
+
e = nil
|
374
|
+
assert_raise(exception_class) do
|
375
|
+
begin
|
376
|
+
yield
|
377
|
+
rescue exception_class => e
|
378
|
+
raise e
|
379
|
+
end
|
380
|
+
end
|
381
|
+
|
382
|
+
e
|
383
|
+
end
|
306
384
|
end
|
data/test/writer_test.rb
CHANGED
@@ -230,36 +230,48 @@ class WriterTest < Test::Unit::TestCase
|
|
230
230
|
|
231
231
|
test 'write crate with remote files and directories' do
|
232
232
|
orig = ROCrate::Reader.read(fixture_file('uri_heavy_crate').path)
|
233
|
-
|
234
|
-
|
233
|
+
Tempfile.create do |file|
|
234
|
+
ROCrate::Writer.new(orig).write_zip(file)
|
235
235
|
|
236
|
-
|
237
|
-
|
238
|
-
|
236
|
+
Zip::File.open(file) do |zipfile|
|
237
|
+
refute zipfile.find_entry('nih:sha-256;3a2c-8d14-a40b-3755-4abc-5af8-a56d-ba3a-e159-d688-c9b3-f169-6751-4b88-fbd2-6a9f;7')
|
238
|
+
end
|
239
|
+
|
240
|
+
file.rewind
|
241
|
+
|
242
|
+
crate = ROCrate::Reader.read(file)
|
243
|
+
|
244
|
+
dir = crate.get('nih:sha-256;f70e-eb2e-89d0-b3dc-5c99-8541-fa4b-6e64-a194-cf9d-ebd8-ca58-24e7-c47a-553f-86fa;c/')
|
245
|
+
assert dir
|
246
|
+
assert dir.is_a?(ROCrate::Directory)
|
247
|
+
assert dir.remote?
|
248
|
+
assert_empty dir.payload
|
249
|
+
|
250
|
+
file = crate.get('nih:sha-256;3a2c-8d14-a40b-3755-4abc-5af8-a56d-ba3a-e159-d688-c9b3-f169-6751-4b88-fbd2-6a9f;7')
|
251
|
+
assert file
|
252
|
+
assert file.is_a?(ROCrate::File)
|
253
|
+
assert file.remote?
|
254
|
+
assert_empty file.payload
|
255
|
+
|
256
|
+
real_file = crate.get('main.nf')
|
257
|
+
assert real_file
|
258
|
+
assert real_file.is_a?(ROCrate::File)
|
259
|
+
refute real_file.remote?
|
260
|
+
assert_not_empty real_file.payload
|
261
|
+
refute real_file.payload.values.first.remote?
|
262
|
+
refute real_file.payload.values.first.directory?
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
test 'write crate with arcp root identifier' do
|
267
|
+
crate = ROCrate::Reader.read(fixture_file('arcp').path)
|
239
268
|
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
assert dir
|
246
|
-
assert dir.is_a?(ROCrate::Directory)
|
247
|
-
assert dir.remote?
|
248
|
-
assert_empty dir.payload
|
249
|
-
|
250
|
-
file = crate.get('nih:sha-256;3a2c-8d14-a40b-3755-4abc-5af8-a56d-ba3a-e159-d688-c9b3-f169-6751-4b88-fbd2-6a9f;7')
|
251
|
-
assert file
|
252
|
-
assert file.is_a?(ROCrate::File)
|
253
|
-
assert file.remote?
|
254
|
-
assert_empty file.payload
|
255
|
-
|
256
|
-
real_file = crate.get('main.nf')
|
257
|
-
assert real_file
|
258
|
-
assert real_file.is_a?(ROCrate::File)
|
259
|
-
refute real_file.remote?
|
260
|
-
assert_not_empty real_file.payload
|
261
|
-
refute real_file.payload.values.first.remote?
|
262
|
-
refute real_file.payload.values.first.directory?
|
269
|
+
assert_equal 'arcp://name,somethingsomething', crate.id
|
270
|
+
Dir.mktmpdir do |dir|
|
271
|
+
ROCrate::Writer.new(crate).write(dir)
|
272
|
+
Dir.chdir(dir) do
|
273
|
+
assert File.exist?('ro-crate-metadata.json')
|
263
274
|
end
|
275
|
+
end
|
264
276
|
end
|
265
277
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ro-crate
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Finn Bacall
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-04-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: addressable
|
@@ -139,7 +139,6 @@ files:
|
|
139
139
|
- ".gitignore"
|
140
140
|
- ".ruby-version"
|
141
141
|
- Gemfile
|
142
|
-
- Gemfile.lock
|
143
142
|
- LICENSE
|
144
143
|
- README.md
|
145
144
|
- Rakefile
|
@@ -152,6 +151,8 @@ files:
|
|
152
151
|
- lib/ro_crate/model/directory.rb
|
153
152
|
- lib/ro_crate/model/entity.rb
|
154
153
|
- lib/ro_crate/model/entry.rb
|
154
|
+
- lib/ro_crate/model/exceptions/exception.rb
|
155
|
+
- lib/ro_crate/model/exceptions/read_exception.rb
|
155
156
|
- lib/ro_crate/model/file.rb
|
156
157
|
- lib/ro_crate/model/metadata.rb
|
157
158
|
- lib/ro_crate/model/organization.rb
|
@@ -166,12 +167,22 @@ files:
|
|
166
167
|
- test/crate_test.rb
|
167
168
|
- test/directory_test.rb
|
168
169
|
- test/entity_test.rb
|
170
|
+
- test/entry_test.rb
|
171
|
+
- test/fixtures/arcp/ro-crate-metadata.json
|
169
172
|
- test/fixtures/biobb_hpc_workflows-condapack.zip
|
173
|
+
- test/fixtures/broken/missing_file/file2.txt
|
174
|
+
- test/fixtures/broken/missing_file/ro-crate-metadata.json
|
175
|
+
- test/fixtures/broken/no_graph/ro-crate-metadata.json
|
176
|
+
- test/fixtures/broken/no_metadata_entity/ro-crate-metadata.json
|
177
|
+
- test/fixtures/broken/no_metadata_file/test.txt
|
178
|
+
- test/fixtures/broken/no_root_entity/ro-crate-metadata.json
|
179
|
+
- test/fixtures/broken/not_json/ro-crate-metadata.json
|
170
180
|
- test/fixtures/conflicting_data_directory/info.txt
|
171
181
|
- test/fixtures/conflicting_data_directory/nested.txt
|
172
182
|
- test/fixtures/crate-spec1.1/file with spaces.txt
|
173
183
|
- test/fixtures/crate-spec1.1/ro-crate-metadata.json
|
174
184
|
- test/fixtures/data.csv
|
185
|
+
- test/fixtures/dir_symlink
|
175
186
|
- test/fixtures/directory.zip
|
176
187
|
- test/fixtures/directory/.dir/test.txt
|
177
188
|
- test/fixtures/directory/.dotfile
|
@@ -210,6 +221,7 @@ files:
|
|
210
221
|
- test/fixtures/sparse_directory_crate/ro-crate-metadata.jsonld
|
211
222
|
- test/fixtures/sparse_directory_crate/ro-crate-preview.html
|
212
223
|
- test/fixtures/sparse_directory_crate/unlisted_file.txt
|
224
|
+
- test/fixtures/symlink
|
213
225
|
- test/fixtures/unlinked_entity_crate/LICENSE
|
214
226
|
- test/fixtures/unlinked_entity_crate/README.md
|
215
227
|
- test/fixtures/unlinked_entity_crate/ro-crate-metadata.json
|
data/Gemfile.lock
DELETED
@@ -1,50 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: .
|
3
|
-
specs:
|
4
|
-
ro-crate (0.5.1)
|
5
|
-
addressable (>= 2.7, < 2.9)
|
6
|
-
rubyzip (~> 2.0.0)
|
7
|
-
|
8
|
-
GEM
|
9
|
-
remote: https://rubygems.org/
|
10
|
-
specs:
|
11
|
-
addressable (2.8.0)
|
12
|
-
public_suffix (>= 2.0.2, < 5.0)
|
13
|
-
crack (0.4.3)
|
14
|
-
safe_yaml (~> 1.0.0)
|
15
|
-
docile (1.3.5)
|
16
|
-
hashdiff (1.0.1)
|
17
|
-
power_assert (2.0.1)
|
18
|
-
public_suffix (4.0.6)
|
19
|
-
rake (13.0.0)
|
20
|
-
rexml (3.2.5)
|
21
|
-
rubyzip (2.0.0)
|
22
|
-
safe_yaml (1.0.5)
|
23
|
-
simplecov (0.21.2)
|
24
|
-
docile (~> 1.1)
|
25
|
-
simplecov-html (~> 0.11)
|
26
|
-
simplecov_json_formatter (~> 0.1)
|
27
|
-
simplecov-html (0.12.3)
|
28
|
-
simplecov_json_formatter (0.1.2)
|
29
|
-
test-unit (3.5.3)
|
30
|
-
power_assert
|
31
|
-
webmock (3.8.3)
|
32
|
-
addressable (>= 2.3.6)
|
33
|
-
crack (>= 0.3.2)
|
34
|
-
hashdiff (>= 0.4.0, < 2.0.0)
|
35
|
-
yard (0.9.25)
|
36
|
-
|
37
|
-
PLATFORMS
|
38
|
-
ruby
|
39
|
-
|
40
|
-
DEPENDENCIES
|
41
|
-
rake (~> 13.0.0)
|
42
|
-
rexml (~> 3.2.5)
|
43
|
-
ro-crate!
|
44
|
-
simplecov (~> 0.21.2)
|
45
|
-
test-unit (~> 3.5.3)
|
46
|
-
webmock (~> 3.8.3)
|
47
|
-
yard (~> 0.9.25)
|
48
|
-
|
49
|
-
BUNDLED WITH
|
50
|
-
2.3.6
|