ro-crate 0.4.8 → 0.4.12
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/Gemfile.lock +13 -13
- data/README.md +39 -0
- data/lib/ro_crate/model/contextual_entity.rb +2 -14
- data/lib/ro_crate/model/crate.rb +52 -6
- data/lib/ro_crate/model/data_entity.rb +6 -5
- data/lib/ro_crate/model/directory.rb +3 -5
- data/lib/ro_crate/model/entity.rb +65 -6
- data/lib/ro_crate/model/entry.rb +2 -2
- data/lib/ro_crate/model/file.rb +2 -4
- data/lib/ro_crate/model/metadata.rb +9 -1
- data/lib/ro_crate/model/organization.rb +1 -1
- data/lib/ro_crate/model/preview.rb +3 -15
- data/lib/ro_crate/model/preview_generator.rb +40 -0
- data/lib/ro_crate/model/remote_entry.rb +1 -12
- data/lib/ro_crate/reader.rb +77 -20
- data/lib/ro_crate/writer.rb +4 -4
- data/lib/ro_crate.rb +2 -1
- data/ro_crate.gemspec +3 -3
- data/test/crate_test.rb +37 -3
- data/test/directory_test.rb +21 -21
- data/test/entity_test.rb +135 -0
- data/test/fixtures/biobb_hpc_workflows-condapack.zip +0 -0
- data/test/fixtures/conflicting_data_directory/info.txt +1 -0
- data/test/fixtures/conflicting_data_directory/nested.txt +1 -0
- data/test/fixtures/nested_directory.zip +0 -0
- data/test/fixtures/ro-crate-galaxy-sortchangecase/LICENSE +176 -0
- data/test/fixtures/ro-crate-galaxy-sortchangecase/README.md +6 -0
- data/test/fixtures/ro-crate-galaxy-sortchangecase/ro-crate-metadata.json +133 -0
- data/test/fixtures/ro-crate-galaxy-sortchangecase/sort-and-change-case.ga +118 -0
- data/test/fixtures/ro-crate-galaxy-sortchangecase/test/test1/input.bed +3 -0
- data/test/fixtures/ro-crate-galaxy-sortchangecase/test/test1/output_exp.bed +3 -0
- data/test/fixtures/ro-crate-galaxy-sortchangecase/test/test1/sort-and-change-case-test.yml +8 -0
- data/test/fixtures/sparse_directory_crate/ro-crate-preview.html +60 -59
- data/test/reader_test.rb +83 -40
- data/test/test_helper.rb +5 -1
- data/test/writer_test.rb +59 -2
- metadata +26 -8
data/lib/ro_crate/reader.rb
CHANGED
@@ -31,7 +31,7 @@ module ROCrate
|
|
31
31
|
def self.unzip_to(source, target)
|
32
32
|
source = Pathname.new(::File.expand_path(source)) if source.is_a?(String)
|
33
33
|
|
34
|
-
if source.is_a?(Pathname) || source.
|
34
|
+
if source.is_a?(Pathname) || source.respond_to?(:path)
|
35
35
|
unzip_file_to(source, target)
|
36
36
|
else
|
37
37
|
unzip_io_to(source, target)
|
@@ -84,7 +84,10 @@ module ROCrate
|
|
84
84
|
def self.read_zip(source, target_dir: Dir.mktmpdir)
|
85
85
|
unzip_to(source, target_dir)
|
86
86
|
|
87
|
-
|
87
|
+
# Traverse the unzipped directory to try and find the crate's root
|
88
|
+
root_dir = detect_root_directory(target_dir)
|
89
|
+
|
90
|
+
read_directory(root_dir)
|
88
91
|
end
|
89
92
|
|
90
93
|
##
|
@@ -100,8 +103,12 @@ module ROCrate
|
|
100
103
|
entry == ROCrate::Metadata::IDENTIFIER_1_0 }
|
101
104
|
|
102
105
|
if metadata_file
|
103
|
-
|
104
|
-
|
106
|
+
metadata_json = ::File.read(::File.join(source, metadata_file))
|
107
|
+
metadata = JSON.parse(metadata_json)
|
108
|
+
entities = entities_from_metadata(metadata)
|
109
|
+
context = metadata['@context']
|
110
|
+
|
111
|
+
build_crate(entities, source, context: context)
|
105
112
|
else
|
106
113
|
raise 'No metadata found!'
|
107
114
|
end
|
@@ -110,10 +117,9 @@ module ROCrate
|
|
110
117
|
##
|
111
118
|
# Extracts all the entities from the @graph of the RO-Crate Metadata.
|
112
119
|
#
|
113
|
-
# @param
|
120
|
+
# @param metadata [Hash] A Hash containing the parsed metadata JSON.
|
114
121
|
# @return [Hash{String => Hash}] A Hash of all the entities, mapped by their @id.
|
115
|
-
def self.entities_from_metadata(
|
116
|
-
metadata = JSON.parse(metadata_json)
|
122
|
+
def self.entities_from_metadata(metadata)
|
117
123
|
graph = metadata['@graph']
|
118
124
|
|
119
125
|
if graph
|
@@ -126,6 +132,7 @@ module ROCrate
|
|
126
132
|
# Do some normalization...
|
127
133
|
entities[ROCrate::Metadata::IDENTIFIER] = extract_metadata_entity(entities)
|
128
134
|
raise "No metadata entity found in @graph!" unless entities[ROCrate::Metadata::IDENTIFIER]
|
135
|
+
entities[ROCrate::Preview::IDENTIFIER] = extract_preview_entity(entities)
|
129
136
|
entities[ROCrate::Crate::IDENTIFIER] = extract_root_entity(entities)
|
130
137
|
raise "No root entity (with @id: #{entities[ROCrate::Metadata::IDENTIFIER].dig('about', '@id')}) found in @graph!" unless entities[ROCrate::Crate::IDENTIFIER]
|
131
138
|
|
@@ -136,25 +143,50 @@ module ROCrate
|
|
136
143
|
end
|
137
144
|
|
138
145
|
##
|
139
|
-
# Create
|
146
|
+
# Create and populate crate from the given set of entities.
|
140
147
|
#
|
141
148
|
# @param entity_hash [Hash{String => Hash}] A Hash containing all the entities in the @graph, mapped by their @id.
|
142
149
|
# @param source [String, ::File, Pathname] The location of the RO-Crate being read.
|
150
|
+
# @param crate_class [Class] The class to use to instantiate the crate,
|
151
|
+
# useful if you have created a subclass of ROCrate::Crate that you want to use. (defaults to ROCrate::Crate).
|
152
|
+
# @param context [nil, String, Array, Hash] A custom JSON-LD @context (parsed), or nil to use default.
|
143
153
|
# @return [Crate] The RO-Crate.
|
144
|
-
def self.build_crate(entity_hash, source)
|
145
|
-
|
154
|
+
def self.build_crate(entity_hash, source, crate_class: ROCrate::Crate, context:)
|
155
|
+
crate = initialize_crate(entity_hash, source, crate_class: crate_class, context: context)
|
156
|
+
|
157
|
+
extract_data_entities(crate, source, entity_hash).each do |entity|
|
158
|
+
crate.add_data_entity(entity)
|
159
|
+
end
|
160
|
+
|
161
|
+
# The remaining entities in the hash must be contextual.
|
162
|
+
extract_contextual_entities(crate, entity_hash).each do |entity|
|
163
|
+
crate.add_contextual_entity(entity)
|
164
|
+
end
|
165
|
+
|
166
|
+
crate
|
167
|
+
end
|
168
|
+
|
169
|
+
##
|
170
|
+
# Initialize a crate from the given set of entities.
|
171
|
+
#
|
172
|
+
# @param entity_hash [Hash{String => Hash}] A Hash containing all the entities in the @graph, mapped by their @id.
|
173
|
+
# @param source [String, ::File, Pathname] The location of the RO-Crate being read.
|
174
|
+
# @param crate_class [Class] The class to use to instantiate the crate,
|
175
|
+
# useful if you have created a subclass of ROCrate::Crate that you want to use. (defaults to ROCrate::Crate).
|
176
|
+
# @param context [nil, String, Array, Hash] A custom JSON-LD @context (parsed), or nil to use default.
|
177
|
+
# @return [Crate] The RO-Crate.
|
178
|
+
def self.initialize_crate(entity_hash, source, crate_class: ROCrate::Crate, context:)
|
179
|
+
crate_class.new.tap do |crate|
|
146
180
|
crate.properties = entity_hash.delete(ROCrate::Crate::IDENTIFIER)
|
147
181
|
crate.metadata.properties = entity_hash.delete(ROCrate::Metadata::IDENTIFIER)
|
182
|
+
crate.metadata.context = context
|
148
183
|
preview_properties = entity_hash.delete(ROCrate::Preview::IDENTIFIER)
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
crate.
|
153
|
-
end
|
154
|
-
# The remaining entities in the hash must be contextual.
|
155
|
-
extract_contextual_entities(crate, entity_hash).each do |entity|
|
156
|
-
crate.add_contextual_entity(entity)
|
184
|
+
preview_path = ::File.join(source, ROCrate::Preview::IDENTIFIER)
|
185
|
+
preview_path = ::File.exists?(preview_path) ? Pathname.new(preview_path) : nil
|
186
|
+
if preview_properties || preview_path
|
187
|
+
crate.preview = ROCrate::Preview.new(crate, preview_path, preview_properties || {})
|
157
188
|
end
|
189
|
+
crate.add_all(source, false)
|
158
190
|
end
|
159
191
|
end
|
160
192
|
|
@@ -226,8 +258,8 @@ module ROCrate
|
|
226
258
|
##
|
227
259
|
# Extract the metadata entity from the entity hash, according to the rules defined here:
|
228
260
|
# https://www.researchobject.org/ro-crate/1.1/root-data-entity.html#finding-the-root-data-entity
|
229
|
-
# @return [Hash{String => Hash}] A Hash containing (hopefully) one value, the metadata entity's properties
|
230
|
-
# mapped by its @id.
|
261
|
+
# @return [nil, Hash{String => Hash}] A Hash containing (hopefully) one value, the metadata entity's properties
|
262
|
+
# mapped by its @id, or nil if nothing is found.
|
231
263
|
def self.extract_metadata_entity(entities)
|
232
264
|
key = entities.detect do |_, props|
|
233
265
|
props.dig('conformsTo', '@id')&.start_with?(ROCrate::Metadata::RO_CRATE_BASE)
|
@@ -242,6 +274,13 @@ module ROCrate
|
|
242
274
|
entities.delete(ROCrate::Metadata::IDENTIFIER_1_0))
|
243
275
|
end
|
244
276
|
|
277
|
+
##
|
278
|
+
# Extract the ro-crate-preview entity from the entity hash.
|
279
|
+
# @return [Hash{String => Hash}] A Hash containing the preview entity's properties mapped by its @id, or nil if nothing is found.
|
280
|
+
def self.extract_preview_entity(entities)
|
281
|
+
entities.delete("./#{ROCrate::Preview::IDENTIFIER}") || entities.delete(ROCrate::Preview::IDENTIFIER)
|
282
|
+
end
|
283
|
+
|
245
284
|
##
|
246
285
|
# Extract the root entity from the entity hash, according to the rules defined here:
|
247
286
|
# https://www.researchobject.org/ro-crate/1.1/root-data-entity.html#finding-the-root-data-entity
|
@@ -252,5 +291,23 @@ module ROCrate
|
|
252
291
|
raise "Metadata entity does not reference any root entity" unless root_id
|
253
292
|
entities.delete(root_id)
|
254
293
|
end
|
294
|
+
|
295
|
+
##
|
296
|
+
# Finds an RO-Crate's root directory (where `ro-crate-metdata.json` is located) within a given directory.
|
297
|
+
#
|
298
|
+
# @param source [String, ::File, Pathname] The location of the directory.
|
299
|
+
# @return [Pathname, nil] The path to the root, or nil if not found.
|
300
|
+
def self.detect_root_directory(source)
|
301
|
+
Pathname(source).find do |entry|
|
302
|
+
if entry.file?
|
303
|
+
name = entry.basename.to_s
|
304
|
+
if name == ROCrate::Metadata::IDENTIFIER || name == ROCrate::Metadata::IDENTIFIER_1_0
|
305
|
+
return entry.parent
|
306
|
+
end
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
310
|
+
nil
|
311
|
+
end
|
255
312
|
end
|
256
313
|
end
|
data/lib/ro_crate/writer.rb
CHANGED
@@ -16,14 +16,14 @@ module ROCrate
|
|
16
16
|
# @param overwrite [Boolean] Whether or not to overwrite existing files.
|
17
17
|
def write(dir, overwrite: true)
|
18
18
|
FileUtils.mkdir_p(dir) # Make any parent directories
|
19
|
-
@crate.
|
19
|
+
@crate.payload.each do |path, entry|
|
20
20
|
fullpath = ::File.join(dir, path)
|
21
21
|
next if !overwrite && ::File.exist?(fullpath)
|
22
22
|
next if entry.directory?
|
23
23
|
FileUtils.mkdir_p(::File.dirname(fullpath))
|
24
24
|
temp = Tempfile.new('ro-crate-temp')
|
25
25
|
begin
|
26
|
-
entry.
|
26
|
+
entry.write_to(temp)
|
27
27
|
temp.close
|
28
28
|
FileUtils.mv(temp, fullpath)
|
29
29
|
ensure
|
@@ -38,9 +38,9 @@ module ROCrate
|
|
38
38
|
# @param destination [String, ::File] The destination where to write the RO-Crate zip.
|
39
39
|
def write_zip(destination)
|
40
40
|
Zip::File.open(destination, Zip::File::CREATE) do |zip|
|
41
|
-
@crate.
|
41
|
+
@crate.payload.each do |path, entry|
|
42
42
|
next if entry.directory?
|
43
|
-
zip.get_output_stream(path) { |s| entry.
|
43
|
+
zip.get_output_stream(path) { |s| entry.write_to(s) }
|
44
44
|
end
|
45
45
|
end
|
46
46
|
end
|
data/lib/ro_crate.rb
CHANGED
@@ -10,10 +10,11 @@ require 'ro_crate/json_ld_hash'
|
|
10
10
|
require 'ro_crate/model/entity'
|
11
11
|
require 'ro_crate/model/data_entity'
|
12
12
|
require 'ro_crate/model/file'
|
13
|
-
require 'ro_crate/model/remote_entry'
|
14
13
|
require 'ro_crate/model/entry'
|
14
|
+
require 'ro_crate/model/remote_entry'
|
15
15
|
require 'ro_crate/model/directory'
|
16
16
|
require 'ro_crate/model/metadata'
|
17
|
+
require 'ro_crate/model/preview_generator'
|
17
18
|
require 'ro_crate/model/preview'
|
18
19
|
require 'ro_crate/model/crate'
|
19
20
|
require 'ro_crate/model/contextual_entity'
|
data/ro_crate.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'ro-crate'
|
3
|
-
s.version = '0.4.
|
3
|
+
s.version = '0.4.12'
|
4
4
|
s.summary = 'Create, manipulate, read RO-Crates.'
|
5
5
|
s.authors = ['Finn Bacall']
|
6
6
|
s.email = 'finn.bacall@manchester.ac.uk'
|
@@ -8,11 +8,11 @@ Gem::Specification.new do |s|
|
|
8
8
|
s.homepage = 'https://github.com/ResearchObject/ro-crate-ruby'
|
9
9
|
s.require_paths = ['lib']
|
10
10
|
s.licenses = ['MIT']
|
11
|
-
s.add_runtime_dependency 'addressable', '
|
11
|
+
s.add_runtime_dependency 'addressable', '>= 2.7', '< 2.9'
|
12
12
|
s.add_runtime_dependency 'rubyzip', '~> 2.0.0'
|
13
13
|
s.add_development_dependency 'rake', '~> 13.0.0'
|
14
14
|
s.add_development_dependency 'test-unit', '~> 3.2.3'
|
15
|
-
s.add_development_dependency 'simplecov', '~> 0.
|
15
|
+
s.add_development_dependency 'simplecov', '~> 0.21.2'
|
16
16
|
s.add_development_dependency 'yard', '~> 0.9.25'
|
17
17
|
s.add_development_dependency 'webmock', '~> 3.8.3'
|
18
18
|
end
|
data/test/crate_test.rb
CHANGED
@@ -164,6 +164,18 @@ class CrateTest < Test::Unit::TestCase
|
|
164
164
|
assert_equal 2, crate1.contextual_entities.first.properties['cats']
|
165
165
|
end
|
166
166
|
|
167
|
+
test 'sharing entities' do
|
168
|
+
crate = ROCrate::Crate.new
|
169
|
+
info = crate.add_file(fixture_file('info.txt'),'the_info.txt')
|
170
|
+
bob = crate.add_person('bob', name: 'Bob Jones')
|
171
|
+
crate.author = bob
|
172
|
+
info.author = bob
|
173
|
+
|
174
|
+
assert_equal [bob], crate.contextual_entities
|
175
|
+
assert_equal bob, info.author
|
176
|
+
assert_equal bob, crate.author
|
177
|
+
end
|
178
|
+
|
167
179
|
test 'external files' do
|
168
180
|
crate = ROCrate::Crate.new
|
169
181
|
local = crate.add_file(fixture_file('info.txt'))
|
@@ -203,7 +215,7 @@ class CrateTest < Test::Unit::TestCase
|
|
203
215
|
crate = ROCrate::Crate.new
|
204
216
|
entities = crate.add_all(fixture_file('directory').path, include_hidden: true)
|
205
217
|
|
206
|
-
paths = crate.
|
218
|
+
paths = crate.payload.keys
|
207
219
|
assert_equal 11, paths.length
|
208
220
|
assert_includes paths, 'data'
|
209
221
|
assert_includes paths, 'root.txt'
|
@@ -238,7 +250,7 @@ class CrateTest < Test::Unit::TestCase
|
|
238
250
|
|
239
251
|
assert_empty entities
|
240
252
|
|
241
|
-
paths = crate.
|
253
|
+
paths = crate.payload.keys
|
242
254
|
assert_equal 11, paths.length
|
243
255
|
assert_includes paths, 'data'
|
244
256
|
assert_includes paths, 'root.txt'
|
@@ -266,7 +278,7 @@ class CrateTest < Test::Unit::TestCase
|
|
266
278
|
crate = ROCrate::Crate.new
|
267
279
|
entities = crate.add_all(fixture_file('directory').path)
|
268
280
|
|
269
|
-
paths = crate.
|
281
|
+
paths = crate.payload.keys
|
270
282
|
assert_equal 8, paths.length
|
271
283
|
assert_includes paths, 'data'
|
272
284
|
assert_includes paths, 'root.txt'
|
@@ -293,4 +305,26 @@ class CrateTest < Test::Unit::TestCase
|
|
293
305
|
|
294
306
|
assert_equal "5678\n", crate.dereference('data/info.txt').source.read
|
295
307
|
end
|
308
|
+
|
309
|
+
test 'can delete entities' do
|
310
|
+
crate = ROCrate::Crate.new
|
311
|
+
file = crate.add_file(StringIO.new(''), 'file')
|
312
|
+
person = crate.add_person('#bob', { name: 'Bob' })
|
313
|
+
file.author = person
|
314
|
+
|
315
|
+
assert crate.delete(file)
|
316
|
+
assert_not_include crate.entities, file
|
317
|
+
assert_not_include crate.entities, person
|
318
|
+
end
|
319
|
+
|
320
|
+
test 'can delete entities by id' do
|
321
|
+
crate = ROCrate::Crate.new
|
322
|
+
file = crate.add_file(StringIO.new(''), 'file')
|
323
|
+
person = crate.add_person('#bob', { name: 'Bob' })
|
324
|
+
file.author = person
|
325
|
+
|
326
|
+
assert crate.delete('file')
|
327
|
+
assert_not_include crate.entities, file
|
328
|
+
assert_not_include crate.entities, person
|
329
|
+
end
|
296
330
|
end
|
data/test/directory_test.rb
CHANGED
@@ -5,41 +5,41 @@ class DirectoryTest < Test::Unit::TestCase
|
|
5
5
|
crate = ROCrate::Crate.new
|
6
6
|
crate.add_directory(fixture_file('directory'))
|
7
7
|
|
8
|
-
|
8
|
+
payload = crate.payload
|
9
9
|
base_path = ::File.dirname(fixture_file('directory'))
|
10
|
-
assert_equal ::File.expand_path(::File.join(base_path, 'directory/info.txt')),
|
11
|
-
assert_equal ::File.expand_path(::File.join(base_path, 'directory/root.txt')),
|
12
|
-
assert_equal ::File.expand_path(::File.join(base_path, 'directory/data')),
|
13
|
-
assert_equal ::File.expand_path(::File.join(base_path, 'directory/data/info.txt')),
|
14
|
-
assert_equal ::File.expand_path(::File.join(base_path, 'directory/data/nested.txt')),
|
15
|
-
assert_equal ::File.expand_path(::File.join(base_path, 'directory/data/binary.jpg')),
|
10
|
+
assert_equal ::File.expand_path(::File.join(base_path, 'directory/info.txt')), payload['directory/info.txt'].path
|
11
|
+
assert_equal ::File.expand_path(::File.join(base_path, 'directory/root.txt')), payload['directory/root.txt'].path
|
12
|
+
assert_equal ::File.expand_path(::File.join(base_path, 'directory/data')), payload['directory/data'].path
|
13
|
+
assert_equal ::File.expand_path(::File.join(base_path, 'directory/data/info.txt')), payload['directory/data/info.txt'].path
|
14
|
+
assert_equal ::File.expand_path(::File.join(base_path, 'directory/data/nested.txt')), payload['directory/data/nested.txt'].path
|
15
|
+
assert_equal ::File.expand_path(::File.join(base_path, 'directory/data/binary.jpg')), payload['directory/data/binary.jpg'].path
|
16
16
|
end
|
17
17
|
|
18
18
|
test 'adding directory via path' do
|
19
19
|
crate = ROCrate::Crate.new
|
20
20
|
crate.add_directory(fixture_file('directory').path.to_s)
|
21
21
|
|
22
|
-
|
22
|
+
payload = crate.payload
|
23
23
|
base_path = ::File.dirname(fixture_file('directory'))
|
24
|
-
assert_equal ::File.expand_path(::File.join(base_path, 'directory/info.txt')),
|
25
|
-
assert_equal ::File.expand_path(::File.join(base_path, 'directory/root.txt')),
|
26
|
-
assert_equal ::File.expand_path(::File.join(base_path, 'directory/data')),
|
27
|
-
assert_equal ::File.expand_path(::File.join(base_path, 'directory/data/info.txt')),
|
28
|
-
assert_equal ::File.expand_path(::File.join(base_path, 'directory/data/nested.txt')),
|
29
|
-
assert_equal ::File.expand_path(::File.join(base_path, 'directory/data/binary.jpg')),
|
24
|
+
assert_equal ::File.expand_path(::File.join(base_path, 'directory/info.txt')), payload['directory/info.txt'].path
|
25
|
+
assert_equal ::File.expand_path(::File.join(base_path, 'directory/root.txt')), payload['directory/root.txt'].path
|
26
|
+
assert_equal ::File.expand_path(::File.join(base_path, 'directory/data')), payload['directory/data'].path
|
27
|
+
assert_equal ::File.expand_path(::File.join(base_path, 'directory/data/info.txt')), payload['directory/data/info.txt'].path
|
28
|
+
assert_equal ::File.expand_path(::File.join(base_path, 'directory/data/nested.txt')), payload['directory/data/nested.txt'].path
|
29
|
+
assert_equal ::File.expand_path(::File.join(base_path, 'directory/data/binary.jpg')), payload['directory/data/binary.jpg'].path
|
30
30
|
end
|
31
31
|
|
32
32
|
test 'adding to given path' do
|
33
33
|
crate = ROCrate::Crate.new
|
34
34
|
crate.add_directory(fixture_file('directory').path.to_s, 'fish')
|
35
35
|
|
36
|
-
|
36
|
+
payload = crate.payload
|
37
37
|
base_path = ::File.dirname(fixture_file('directory'))
|
38
|
-
assert_equal ::File.expand_path(::File.join(base_path, 'directory/info.txt')),
|
39
|
-
assert_equal ::File.expand_path(::File.join(base_path, 'directory/root.txt')),
|
40
|
-
assert_equal ::File.expand_path(::File.join(base_path, 'directory/data')),
|
41
|
-
assert_equal ::File.expand_path(::File.join(base_path, 'directory/data/info.txt')),
|
42
|
-
assert_equal ::File.expand_path(::File.join(base_path, 'directory/data/nested.txt')),
|
43
|
-
assert_equal ::File.expand_path(::File.join(base_path, 'directory/data/binary.jpg')),
|
38
|
+
assert_equal ::File.expand_path(::File.join(base_path, 'directory/info.txt')), payload['fish/info.txt'].path
|
39
|
+
assert_equal ::File.expand_path(::File.join(base_path, 'directory/root.txt')), payload['fish/root.txt'].path
|
40
|
+
assert_equal ::File.expand_path(::File.join(base_path, 'directory/data')), payload['fish/data'].path
|
41
|
+
assert_equal ::File.expand_path(::File.join(base_path, 'directory/data/info.txt')), payload['fish/data/info.txt'].path
|
42
|
+
assert_equal ::File.expand_path(::File.join(base_path, 'directory/data/nested.txt')), payload['fish/data/nested.txt'].path
|
43
|
+
assert_equal ::File.expand_path(::File.join(base_path, 'directory/data/binary.jpg')), payload['fish/data/binary.jpg'].path
|
44
44
|
end
|
45
45
|
end
|
data/test/entity_test.rb
CHANGED
@@ -70,4 +70,139 @@ class EntityTest < Test::Unit::TestCase
|
|
70
70
|
assert_equal({ '@id' => '#fred' }, person.reference)
|
71
71
|
assert_equal(person.canonical_id, crate.author.canonical_id)
|
72
72
|
end
|
73
|
+
|
74
|
+
test 'format various IDs' do
|
75
|
+
assert_equal "#Hello%20World/Goodbye%20World", ROCrate::ContextualEntity.format_id('#Hello World/Goodbye World')
|
76
|
+
assert_equal "#Hello%20World/Goodbye%20World", ROCrate::ContextualEntity.format_id('Hello World/Goodbye World')
|
77
|
+
assert_equal "#%F0%9F%98%8A", ROCrate::ContextualEntity.format_id("😊")
|
78
|
+
|
79
|
+
assert_equal "test123/hello.txt", ROCrate::File.format_id('./test123/hello.txt')
|
80
|
+
assert_equal "test123/hello.txt", ROCrate::File.format_id('./test123/hello.txt/')
|
81
|
+
assert_equal "http://www.data.com/my%20data.txt", ROCrate::File.format_id('http://www.data.com/my%20data.txt')
|
82
|
+
assert_equal "http://www.data.com/my%20data.txt/", ROCrate::File.format_id('http://www.data.com/my%20data.txt/'), 'Should not modify absolute URI for DataEntity'
|
83
|
+
|
84
|
+
assert_equal "my%20directory/", ROCrate::Directory.format_id('my directory')
|
85
|
+
assert_equal "my%20directory/", ROCrate::Directory.format_id('my directory/')
|
86
|
+
assert_equal 'http://www.data.com/my%20directory', ROCrate::Directory.format_id('http://www.data.com/my%20directory'), 'Should not modify absolute URI for DataEntity'
|
87
|
+
assert_equal 'http://www.data.com/my%20directory/', ROCrate::Directory.format_id('http://www.data.com/my%20directory/'), 'Should not modify absolute URI for DataEntity'
|
88
|
+
|
89
|
+
assert_equal "./", ROCrate::Crate.format_id('./')
|
90
|
+
assert_equal "cool%20crate/", ROCrate::Crate.format_id('./cool crate')
|
91
|
+
assert_equal "http://www.data.com/my%20crate/", ROCrate::Crate.format_id('http://www.data.com/my%20crate'), 'Crate ID should end with /'
|
92
|
+
assert_equal "http://www.data.com/my%20crate/", ROCrate::Crate.format_id('http://www.data.com/my%20crate/')
|
93
|
+
end
|
94
|
+
|
95
|
+
test 'linked entities' do
|
96
|
+
crate = ROCrate::Crate.new
|
97
|
+
file = crate.add_file(StringIO.new(''), 'file')
|
98
|
+
person = crate.add_person('#bob', { name: 'Bob' })
|
99
|
+
file.author = person
|
100
|
+
|
101
|
+
linked = file.linked_entities
|
102
|
+
assert_include linked, person
|
103
|
+
assert_equal 1, linked.length
|
104
|
+
|
105
|
+
linked = crate.linked_entities
|
106
|
+
assert_include linked, file
|
107
|
+
assert_equal 1, linked.length
|
108
|
+
|
109
|
+
linked = crate.linked_entities(deep: true)
|
110
|
+
assert_include linked, file
|
111
|
+
assert_include linked, person
|
112
|
+
assert_equal 2, linked.length
|
113
|
+
end
|
114
|
+
|
115
|
+
test 'deleting entities removes linked entities' do
|
116
|
+
crate = ROCrate::Crate.new
|
117
|
+
file = crate.add_file(StringIO.new(''), 'file')
|
118
|
+
person = crate.add_person('#bob', { name: 'Bob' })
|
119
|
+
file.author = person
|
120
|
+
|
121
|
+
assert file.delete
|
122
|
+
assert_not_include crate.entities, file
|
123
|
+
assert_not_include crate.entities, person
|
124
|
+
end
|
125
|
+
|
126
|
+
test 'deleting entities does not remove dangling entities if option set' do
|
127
|
+
crate = ROCrate::Crate.new
|
128
|
+
file = crate.add_file(StringIO.new(''), 'file')
|
129
|
+
person = crate.add_person('#bob', { name: 'Bob' })
|
130
|
+
file.author = person
|
131
|
+
|
132
|
+
assert file.delete(remove_orphaned: false)
|
133
|
+
assert_not_include crate.entities, file
|
134
|
+
assert_include crate.entities, person
|
135
|
+
end
|
136
|
+
|
137
|
+
test 'creating files in various ways' do
|
138
|
+
stub_request(:get, 'http://example.com/external_ref.txt').to_return(status: 200, body: 'file contents')
|
139
|
+
|
140
|
+
crate = ROCrate::Crate.new
|
141
|
+
|
142
|
+
f1 = nil
|
143
|
+
Dir.chdir(fixture_dir) { f1 = ROCrate::File.new(crate, 'data.csv') }
|
144
|
+
refute f1.source.remote?
|
145
|
+
refute f1.source.directory?
|
146
|
+
assert_equal 20, f1.source.read.length
|
147
|
+
t = Tempfile.new('tf1')
|
148
|
+
f1.source.write_to(t)
|
149
|
+
t.rewind
|
150
|
+
assert_equal 20, t.read.length
|
151
|
+
|
152
|
+
f2 = ROCrate::File.new(crate, fixture_file('info.txt'), { author: crate.add_person('bob', name: 'Bob').reference })
|
153
|
+
refute f2.source.remote?
|
154
|
+
refute f2.source.directory?
|
155
|
+
assert f2.source.read
|
156
|
+
assert_equal 6, f2.source.read.length
|
157
|
+
t = Tempfile.new('tf2')
|
158
|
+
f2.source.write_to(t)
|
159
|
+
t.rewind
|
160
|
+
assert_equal 6, t.read.length
|
161
|
+
|
162
|
+
f3 = ROCrate::File.new(crate, 'http://example.com/external_ref.txt')
|
163
|
+
assert f3.source.remote?
|
164
|
+
refute f3.source.directory?
|
165
|
+
assert f3.source.read
|
166
|
+
assert_equal 13, f3.source.read.length
|
167
|
+
t = Tempfile.new('tf3')
|
168
|
+
f3.source.write_to(t)
|
169
|
+
t.rewind
|
170
|
+
assert_equal 13, t.read.length
|
171
|
+
|
172
|
+
f3 = ROCrate::File.new(crate, 'http://example.com/external_ref.txt')
|
173
|
+
assert f3.source.remote?
|
174
|
+
refute f3.source.directory?
|
175
|
+
assert f3.source.read
|
176
|
+
assert_equal 13, f3.source.read.length
|
177
|
+
t = Tempfile.new('tf3')
|
178
|
+
f3.source.write_to(t)
|
179
|
+
t.rewind
|
180
|
+
assert_equal 13, t.read.length
|
181
|
+
end
|
182
|
+
|
183
|
+
test 'assigning and checking type' do
|
184
|
+
crate = ROCrate::Crate.new
|
185
|
+
file = ROCrate::File.new(crate, 'data.csv')
|
186
|
+
|
187
|
+
assert file.has_type?('File')
|
188
|
+
|
189
|
+
file.type = ['File', 'Workflow']
|
190
|
+
|
191
|
+
assert file.has_type?('Workflow')
|
192
|
+
assert file.has_type?('File')
|
193
|
+
refute file.has_type?('Banana')
|
194
|
+
end
|
195
|
+
|
196
|
+
test 'inspecting object truncates very long property list' do
|
197
|
+
crate = ROCrate::Crate.new
|
198
|
+
entity = ROCrate::ContextualEntity.new(crate, 'hello')
|
199
|
+
|
200
|
+
assert entity.inspect.start_with?("<#ROCrate::ContextualEntity arcp://uuid,")
|
201
|
+
|
202
|
+
entity['veryLong'] = ('123456789a' * 100)
|
203
|
+
|
204
|
+
ins = entity.inspect
|
205
|
+
assert ins.length < 1000
|
206
|
+
assert ins.end_with?('...>')
|
207
|
+
end
|
73
208
|
end
|
Binary file
|
@@ -0,0 +1 @@
|
|
1
|
+
abcd
|
@@ -0,0 +1 @@
|
|
1
|
+
No, I am nested!
|
Binary file
|