oai 0.0.6 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- data/README +1 -1
- data/Rakefile +1 -3
- data/lib/oai/client.rb +27 -27
- data/lib/oai/harvester.rb +1 -0
- data/lib/oai/harvester/shell.rb +2 -2
- data/lib/oai/provider.rb +4 -4
- data/lib/oai/provider/metadata_format.rb +46 -4
- data/lib/oai/provider/model/activerecord_caching_wrapper.rb +0 -1
- data/lib/oai/provider/model/activerecord_wrapper.rb +2 -2
- data/lib/oai/provider/response.rb +4 -6
- data/lib/oai/provider/response/identify.rb +5 -3
- data/lib/oai/xpath.rb +1 -1
- data/test/activerecord_provider/database/oaipmhtest +0 -0
- data/test/activerecord_provider/helpers/set_provider.rb +1 -1
- data/test/activerecord_provider/tc_ar_provider.rb +31 -24
- data/test/activerecord_provider/tc_ar_sets_provider.rb +12 -6
- data/test/activerecord_provider/tc_caching_paging_provider.rb +22 -21
- data/test/activerecord_provider/tc_simple_paging_provider.rb +23 -22
- data/test/client/tc_exception.rb +3 -3
- data/test/client/tc_list_records.rb +1 -0
- data/test/client/tc_low_resolution_dates.rb +14 -0
- data/test/client/tc_utf8_escaping.rb +11 -0
- data/test/client/tc_xpath.rb +2 -5
- data/test/provider/models.rb +16 -16
- data/test/provider/tc_exceptions.rb +4 -3
- data/test/provider/tc_functional_tokens.rb +2 -2
- data/test/provider/tc_provider.rb +7 -7
- metadata +35 -51
data/README
CHANGED
data/Rakefile
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
RUBY_OAI_VERSION = '0.0.
|
1
|
+
RUBY_OAI_VERSION = '0.0.7'
|
2
2
|
|
3
3
|
require 'rubygems'
|
4
4
|
require 'rake'
|
@@ -25,8 +25,6 @@ spec = Gem::Specification.new do |s|
|
|
25
25
|
s.bindir = 'bin'
|
26
26
|
s.executables = 'oai'
|
27
27
|
|
28
|
-
s.add_dependency('activesupport', '>=1.3.1')
|
29
|
-
s.add_dependency('chronic', '>=0.0.3')
|
30
28
|
s.add_dependency('builder', '>=2.0.0')
|
31
29
|
|
32
30
|
s.files = %w(README Rakefile) +
|
data/lib/oai/client.rb
CHANGED
@@ -155,7 +155,7 @@ module OAI
|
|
155
155
|
def do_request(verb, opts = nil)
|
156
156
|
# fire off the request and return appropriate DOM object
|
157
157
|
uri = build_uri(verb, opts)
|
158
|
-
xml = get(uri)
|
158
|
+
xml = strip_invalid_utf_8_chars(get(uri))
|
159
159
|
if @parser == 'libxml'
|
160
160
|
# remove default namespace for oai-pmh since libxml
|
161
161
|
# isn't able to use our xpaths to get at them
|
@@ -176,15 +176,16 @@ module OAI
|
|
176
176
|
|
177
177
|
def encode(value)
|
178
178
|
return CGI.escape(value) unless value.respond_to?(:strftime)
|
179
|
-
if value.
|
180
|
-
value.
|
179
|
+
if value.kind_of?(DateTime)
|
180
|
+
Time.parse(value.asctime).utc.xmlschema
|
181
|
+
elsif value.kind_of?(Time)
|
182
|
+
value.utc.xmlschema
|
181
183
|
else # Assume something date like
|
182
184
|
value.strftime('%Y-%m-%d')
|
183
185
|
end
|
184
186
|
end
|
185
187
|
|
186
188
|
def load_document(xml)
|
187
|
-
retried = false
|
188
189
|
case @parser
|
189
190
|
when 'libxml'
|
190
191
|
begin
|
@@ -192,28 +193,13 @@ module OAI
|
|
192
193
|
parser.string = xml
|
193
194
|
return parser.parse
|
194
195
|
rescue XML::Parser::ParseError => e
|
195
|
-
|
196
|
-
raise OAI::Exception, 'response not well formed XML: '+e, caller
|
197
|
-
end
|
198
|
-
ic = Iconv.new('UTF-8//IGNORE', 'UTF-8')
|
199
|
-
xml2 = ic.iconv(xml << ' ')[0..-2]
|
200
|
-
puts "equal? #{xml == xml2}"
|
201
|
-
retried = true
|
202
|
-
retry
|
196
|
+
raise OAI::Exception, 'response not well formed XML: '+e, caller
|
203
197
|
end
|
204
198
|
when 'rexml'
|
205
199
|
begin
|
206
200
|
return REXML::Document.new(xml)
|
207
201
|
rescue REXML::ParseException => e
|
208
|
-
|
209
|
-
puts xml
|
210
|
-
raise OAI::Exception, 'response not well formed XML: '+e, caller
|
211
|
-
end
|
212
|
-
puts "RETRYING"
|
213
|
-
ic = Iconv.new('UTF-8//IGNORE', 'UTF-8')
|
214
|
-
xml = ic.iconv(xml << ' ')[0..-2]
|
215
|
-
retried = true
|
216
|
-
retry
|
202
|
+
raise OAI::Exception, 'response not well formed XML: '+e.message, caller
|
217
203
|
end
|
218
204
|
end
|
219
205
|
end
|
@@ -288,13 +274,27 @@ module OAI
|
|
288
274
|
def parse_date(value)
|
289
275
|
return value if value.respond_to?(:strftime)
|
290
276
|
|
291
|
-
#
|
292
|
-
#
|
293
|
-
|
294
|
-
raise OAI::ArgumentError.new
|
295
|
-
|
296
|
-
dt.utc
|
277
|
+
Date.parse(value) # This will raise an exception for badly formatted dates
|
278
|
+
Time.parse(value).utc # Sadly, this will not
|
279
|
+
rescue
|
280
|
+
raise OAI::ArgumentError.new
|
297
281
|
end
|
298
282
|
|
283
|
+
# Strip out invalid UTF-8 characters. Regex from the W3C, inverted.
|
284
|
+
# http://www.w3.org/International/questions/qa-forms-utf-8.en.php
|
285
|
+
#
|
286
|
+
# Regex is from WebCollab:
|
287
|
+
# http://webcollab.sourceforge.net/unicode.html
|
288
|
+
def strip_invalid_utf_8_chars(xml)
|
289
|
+
simple_bytes = xml.gsub(/[\x00-\x08\x10\x0B\x0C\x0E-\x19\x7F]
|
290
|
+
| [\x00-\x7F][\x80-\xBF]+
|
291
|
+
| ([\xC0\xC1]|[\xF0-\xFF])[\x80-\xBF]*
|
292
|
+
| [\xC2-\xDF]((?![\x80-\xBF])|[\x80-\xBF]{2,})
|
293
|
+
| [\xE0-\xEF](([\x80-\xBF](?![\x80-\xBF]))
|
294
|
+
| (?![\x80-\xBF]{2})|[\x80-\xBF]{3,})/x, '?')
|
295
|
+
simple_bytes.gsub(/\xE0[\x80-\x9F][\x80-\xBF]
|
296
|
+
| \xED[\xA0-\xBF][\x80-\xBF]/,'?')
|
297
|
+
end
|
298
|
+
|
299
299
|
end
|
300
300
|
end
|
data/lib/oai/harvester.rb
CHANGED
data/lib/oai/harvester/shell.rb
CHANGED
data/lib/oai/provider.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
require '
|
1
|
+
require 'rexml/document'
|
2
|
+
require 'singleton'
|
2
3
|
require 'builder'
|
3
|
-
require 'chronic'
|
4
4
|
|
5
5
|
if not defined?(OAI::Const::VERBS)
|
6
6
|
require 'oai/exception'
|
@@ -266,8 +266,8 @@ module OAI::Provider
|
|
266
266
|
Response::GetRecord.new(self.class, options).to_xml
|
267
267
|
end
|
268
268
|
|
269
|
-
# xml_response = process_verb('ListRecords', :from => 'October',
|
270
|
-
# :until => 'November')
|
269
|
+
# xml_response = process_verb('ListRecords', :from => 'October 1, 2005',
|
270
|
+
# :until => 'November 1, 2005')
|
271
271
|
#
|
272
272
|
# If you are implementing a web interface using process_request is the
|
273
273
|
# preferred way.
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
|
1
3
|
module OAI::Provider::Metadata
|
2
4
|
# == Metadata Base Class
|
3
5
|
#
|
@@ -54,10 +56,9 @@ module OAI::Provider::Metadata
|
|
54
56
|
def value_for(field, record, map)
|
55
57
|
method = map[field] ? map[field].to_s : field.to_s
|
56
58
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
elsif methods.include?(method)
|
59
|
+
if record.respond_to?(pluralize(method))
|
60
|
+
record.send pluralize(method)
|
61
|
+
elsif record.respond_to?(method)
|
61
62
|
record.send method
|
62
63
|
else
|
63
64
|
[]
|
@@ -68,6 +69,47 @@ module OAI::Provider::Metadata
|
|
68
69
|
def header_specification
|
69
70
|
raise NotImplementedError.new
|
70
71
|
end
|
72
|
+
|
73
|
+
# Shamelessly lifted form ActiveSupport. Thanks Rails community!
|
74
|
+
def pluralize(word)
|
75
|
+
# Use ActiveSupports pluralization if it's available.
|
76
|
+
return word.pluralize if word.respond_to?(:pluralize)
|
77
|
+
|
78
|
+
# Otherwise use our own simple pluralization rules.
|
79
|
+
result = word.to_s.dup
|
80
|
+
|
81
|
+
# Uncountable words
|
82
|
+
return result if %w(equipment information rice money species series fish sheep).include?(result)
|
83
|
+
|
84
|
+
# Irregular words
|
85
|
+
{ 'person' => 'people', 'man' => 'men', 'child' => 'children', 'sex' => 'sexes',
|
86
|
+
'move' => 'moves', 'cow' => 'kine' }.each { |k,v| return v if word == k }
|
87
|
+
|
88
|
+
rules.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }
|
89
|
+
result
|
90
|
+
end
|
91
|
+
|
92
|
+
def rules
|
93
|
+
[
|
94
|
+
[/$/, 's'],
|
95
|
+
[/s$/i, 's'],
|
96
|
+
[/(ax|test)is$/i, '\1es'],
|
97
|
+
[/(octop|vir)us$/i, '\1i'],
|
98
|
+
[/(alias|status)$/i, '\1es'],
|
99
|
+
[/(bu)s$/i, '\1ses'],
|
100
|
+
[/(buffal|tomat)o$/i, '\1oes'],
|
101
|
+
[/([ti])um$/i, '\1a'],
|
102
|
+
[/sis$/i, 'ses'],
|
103
|
+
[/(?:([^f])fe|([lr])f)$/i, '\1\2ves'],
|
104
|
+
[/(hive)$/i, '\1s'],
|
105
|
+
[/([^aeiouy]|qu)y$/i, '\1ies'],
|
106
|
+
[/(x|ch|ss|sh)$/i, '\1es'],
|
107
|
+
[/(matr|vert|ind)(?:ix|ex)$/i, '\1ices'],
|
108
|
+
[/([m|l])ouse$/i, '\1ice'],
|
109
|
+
[/^(ox)$/i, '\1en'],
|
110
|
+
[/(quiz)$/i, '\1zes']
|
111
|
+
]
|
112
|
+
end
|
71
113
|
|
72
114
|
end
|
73
115
|
|
@@ -20,8 +20,8 @@ module OAI::Provider
|
|
20
20
|
@limit = options.delete(:limit)
|
21
21
|
|
22
22
|
unless options.empty?
|
23
|
-
raise
|
24
|
-
"Unsupported options [#{options.join(', ')}]"
|
23
|
+
raise ArgumentError.new(
|
24
|
+
"Unsupported options [#{options.keys.join(', ')}]"
|
25
25
|
)
|
26
26
|
end
|
27
27
|
end
|
@@ -94,12 +94,10 @@ module OAI
|
|
94
94
|
def parse_date(value)
|
95
95
|
return value if value.respond_to?(:strftime)
|
96
96
|
|
97
|
-
#
|
98
|
-
#
|
99
|
-
|
100
|
-
raise OAI::ArgumentError.new
|
101
|
-
|
102
|
-
dt.utc
|
97
|
+
Date.parse(value) # This will raise an exception for badly formatted dates
|
98
|
+
Time.parse(value).utc # Sadly, this will not
|
99
|
+
rescue
|
100
|
+
raise OAI::ArgumentError.new
|
103
101
|
end
|
104
102
|
|
105
103
|
def internalize(hash = {})
|
@@ -8,9 +8,11 @@ module OAI::Provider::Response
|
|
8
8
|
r.repositoryName provider.name
|
9
9
|
r.baseURL provider.url
|
10
10
|
r.protocolVersion 2.0
|
11
|
-
provider.email.each
|
12
|
-
r.adminEmail address
|
13
|
-
|
11
|
+
if provider.email and provider.email.respond_to?(:each)
|
12
|
+
provider.email.each { |address| r.adminEmail address }
|
13
|
+
else
|
14
|
+
r.adminEmail provider.email.to_s
|
15
|
+
end
|
14
16
|
r.earliestDatestamp provider.model.earliest
|
15
17
|
r.deletedRecord provider.delete_support.to_s
|
16
18
|
r.granularity provider.granularity
|
data/lib/oai/xpath.rb
CHANGED
Binary file
|
@@ -32,5 +32,5 @@ class ARSetProvider < OAI::Provider::Base
|
|
32
32
|
repository_name 'ActiveRecord Set Based Provider'
|
33
33
|
repository_url 'http://localhost'
|
34
34
|
record_prefix = 'oai:test'
|
35
|
-
source_model SetModel.new(DCField)
|
35
|
+
source_model SetModel.new(DCField, :timestamp_field => 'date')
|
36
36
|
end
|
@@ -13,7 +13,8 @@ class ActiveRecordProviderTest < Test::Unit::TestCase
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def test_metadata_formats_for_record
|
16
|
-
|
16
|
+
record_id = DCField.find(:first).id
|
17
|
+
assert_nothing_raised { REXML::Document.new(@provider.list_metadata_formats(:identifier => "oai:test/#{record_id}")) }
|
17
18
|
doc = REXML::Document.new(@provider.list_metadata_formats)
|
18
19
|
assert doc.elements['/OAI-PMH/ListMetadataFormats/metadataFormat/metadataPrefix'].text == 'oai_dc'
|
19
20
|
end
|
@@ -31,25 +32,29 @@ class ActiveRecordProviderTest < Test::Unit::TestCase
|
|
31
32
|
end
|
32
33
|
|
33
34
|
def test_get_record
|
34
|
-
|
35
|
-
|
36
|
-
|
35
|
+
record_id = DCField.find(:first).id
|
36
|
+
assert_nothing_raised { REXML::Document.new(@provider.get_record(:identifier => "oai:test/#{record_id}")) }
|
37
|
+
doc = REXML::Document.new(@provider.get_record(:identifier => "#{record_id}"))
|
38
|
+
assert_equal "oai:test/#{record_id}", doc.elements['OAI-PMH/GetRecord/record/header/identifier'].text
|
37
39
|
end
|
38
40
|
|
39
41
|
def test_deleted
|
40
|
-
DCField.
|
41
|
-
|
42
|
-
|
42
|
+
record = DCField.find(:first)
|
43
|
+
record.deleted = true;
|
44
|
+
record.save
|
45
|
+
doc = REXML::Document.new(@provider.get_record(:identifier => "oai:test/#{record.id}"))
|
46
|
+
assert_equal "oai:test/#{record.id}", doc.elements['OAI-PMH/GetRecord/record/header/identifier'].text
|
43
47
|
assert_equal 'deleted', doc.elements['OAI-PMH/GetRecord/record/header'].attributes["status"]
|
44
48
|
end
|
45
49
|
|
46
50
|
def test_from
|
47
|
-
DCField.
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
+
first_id = DCField.find(:first, :order => "id asc").id
|
52
|
+
DCField.update_all(['updated_at = ?', Time.parse("January 1 2005")],
|
53
|
+
"id < #{first_id + 90}")
|
54
|
+
DCField.update_all(['updated_at = ?', Time.parse("June 1 2005")],
|
55
|
+
"id < #{first_id + 10}")
|
51
56
|
|
52
|
-
from_param =
|
57
|
+
from_param = Time.parse("January 1 2006")
|
53
58
|
|
54
59
|
doc = REXML::Document.new(
|
55
60
|
@provider.list_records(:from => from_param)
|
@@ -58,31 +63,33 @@ class ActiveRecordProviderTest < Test::Unit::TestCase
|
|
58
63
|
doc.elements['OAI-PMH/ListRecords'].size
|
59
64
|
|
60
65
|
doc = REXML::Document.new(
|
61
|
-
@provider.list_records(:from =>
|
66
|
+
@provider.list_records(:from => Time.parse("May 30 2005"))
|
62
67
|
)
|
63
68
|
assert_equal 20, doc.elements['OAI-PMH/ListRecords'].to_a.size
|
64
69
|
end
|
65
70
|
|
66
71
|
def test_until
|
67
|
-
DCField.
|
68
|
-
|
72
|
+
first_id = DCField.find(:first, :order => "id asc").id
|
73
|
+
DCField.update_all(['updated_at = ?', Time.parse("June 1 2005")],
|
74
|
+
"id < #{first_id + 10}")
|
69
75
|
|
70
76
|
doc = REXML::Document.new(
|
71
|
-
@provider.list_records(:until =>
|
77
|
+
@provider.list_records(:until => Time.parse("June 1 2005"))
|
72
78
|
)
|
73
|
-
assert_equal
|
79
|
+
assert_equal 10, doc.elements['OAI-PMH/ListRecords'].to_a.size
|
74
80
|
end
|
75
81
|
|
76
82
|
def test_from_and_until
|
77
|
-
DCField.
|
78
|
-
DCField.update_all(['updated_at = ?',
|
79
|
-
|
80
|
-
|
81
|
-
|
83
|
+
first_id = DCField.find(:first, :order => "id asc").id
|
84
|
+
DCField.update_all(['updated_at = ?', Time.parse("June 1 2005")])
|
85
|
+
DCField.update_all(['updated_at = ?', Time.parse("June 15 2005")],
|
86
|
+
"id < #{first_id + 50}")
|
87
|
+
DCField.update_all(['updated_at = ?', Time.parse("June 30 2005")],
|
88
|
+
"id < #{first_id + 10}")
|
82
89
|
|
83
90
|
doc = REXML::Document.new(
|
84
|
-
@provider.list_records(:from =>
|
85
|
-
:until =>
|
91
|
+
@provider.list_records(:from => Time.parse("June 3 2005"),
|
92
|
+
:until => Time.parse("June 16 2005"))
|
86
93
|
)
|
87
94
|
assert_equal 40, doc.elements['OAI-PMH/ListRecords'].to_a.size
|
88
95
|
end
|
@@ -25,7 +25,8 @@ class ActiveRecordSetProviderTest < Test::Unit::TestCase
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def test_record_with_multiple_sets
|
28
|
-
|
28
|
+
record = DCSet.find(:first, :conditions => "spec = 'C'").dc_fields.first
|
29
|
+
assert_equal 2, record.sets.size
|
29
30
|
end
|
30
31
|
|
31
32
|
def setup
|
@@ -43,24 +44,29 @@ class ActiveRecordSetProviderTest < Test::Unit::TestCase
|
|
43
44
|
def define_sets
|
44
45
|
set_a = DCSet.create(:name => "Set A", :spec => "A")
|
45
46
|
set_b = DCSet.create(:name => "Set B", :spec => "B")
|
46
|
-
set_c = DCSet.create(:name => "Set
|
47
|
+
set_c = DCSet.create(:name => "Set C", :spec => "C")
|
47
48
|
set_ab = DCSet.create(:name => "Set A:B", :spec => "A:B")
|
48
49
|
|
49
|
-
|
50
|
+
next_id = 0
|
51
|
+
DCField.find(:all, :limit => 10, :order => "id asc").each do |record|
|
50
52
|
set_a.dc_fields << record
|
53
|
+
next_id = record.id
|
51
54
|
end
|
52
55
|
|
53
|
-
DCField.find(
|
56
|
+
DCField.find(:all, :limit => 10, :order => "id asc", :conditions => "id > #{next_id}").each do |record|
|
54
57
|
set_b.dc_fields << record
|
58
|
+
next_id = record.id
|
55
59
|
end
|
56
60
|
|
57
|
-
DCField.find(
|
61
|
+
DCField.find(:all, :limit => 10, :order => "id asc", :conditions => "id > #{next_id}").each do |record|
|
58
62
|
set_ab.dc_fields << record
|
63
|
+
next_id = record.id
|
59
64
|
end
|
60
65
|
|
61
|
-
DCField.find(
|
66
|
+
DCField.find(:all, :limit => 10, :order => "id asc", :conditions => "id > #{next_id}").each do |record|
|
62
67
|
set_a.dc_fields << record
|
63
68
|
set_c.dc_fields << record
|
69
|
+
next_id = record.id
|
64
70
|
end
|
65
71
|
end
|
66
72
|
end
|
@@ -5,40 +5,41 @@ class CachingPagingProviderTest < Test::Unit::TestCase
|
|
5
5
|
|
6
6
|
def test_full_harvest
|
7
7
|
doc = Document.new(@provider.list_records)
|
8
|
-
assert_not_nil doc.elements["/OAI-PMH/resumptionToken"]
|
9
|
-
assert_equal
|
10
|
-
token = doc.elements["/OAI-PMH/resumptionToken"].text
|
8
|
+
assert_not_nil doc.elements["/OAI-PMH/ListRecords/resumptionToken"]
|
9
|
+
assert_equal 26, doc.elements["/OAI-PMH/ListRecords"].size
|
10
|
+
token = doc.elements["/OAI-PMH/ListRecords/resumptionToken"].text
|
11
11
|
doc = Document.new(@provider.list_records(:resumption_token => token))
|
12
|
-
assert_not_nil doc.elements["/OAI-PMH/resumptionToken"]
|
13
|
-
token = doc.elements["/OAI-PMH/resumptionToken"].text
|
14
|
-
assert_equal
|
12
|
+
assert_not_nil doc.elements["/OAI-PMH/ListRecords/resumptionToken"]
|
13
|
+
token = doc.elements["/OAI-PMH/ListRecords/resumptionToken"].text
|
14
|
+
assert_equal 26, doc.elements["/OAI-PMH/ListRecords"].size
|
15
15
|
doc = Document.new(@provider.list_records(:resumption_token => token))
|
16
|
-
assert_not_nil doc.elements["/OAI-PMH/resumptionToken"]
|
17
|
-
token = doc.elements["/OAI-PMH/resumptionToken"].text
|
18
|
-
assert_equal
|
16
|
+
assert_not_nil doc.elements["/OAI-PMH/ListRecords/resumptionToken"]
|
17
|
+
token = doc.elements["/OAI-PMH/ListRecords/resumptionToken"].text
|
18
|
+
assert_equal 26, doc.elements["/OAI-PMH/ListRecords"].size
|
19
19
|
doc = Document.new(@provider.list_records(:resumption_token => token))
|
20
|
-
assert_nil doc.elements["/OAI-PMH/resumptionToken"]
|
20
|
+
assert_nil doc.elements["/OAI-PMH/ListRecords/resumptionToken"]
|
21
21
|
assert_equal 25, doc.elements["/OAI-PMH/ListRecords"].size
|
22
22
|
end
|
23
23
|
|
24
24
|
def test_from_and_until
|
25
|
-
DCField.
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
25
|
+
first_id = DCField.find(:first, :order => "id asc").id
|
26
|
+
DCField.update_all(['updated_at = ?', Time.parse("September 15 2005")],
|
27
|
+
"id <= #{first_id + 25}")
|
28
|
+
DCField.update_all(['updated_at = ?', Time.parse("November 1 2005")],
|
29
|
+
"id < #{first_id + 50} and id > #{first_id + 25}")
|
30
|
+
|
30
31
|
# Should return 50 records broken into 2 groups of 25.
|
31
32
|
doc = Document.new(
|
32
33
|
@provider.list_records(
|
33
|
-
:from =>
|
34
|
-
:until =>
|
34
|
+
:from => Time.parse("September 1 2005"),
|
35
|
+
:until => Time.parse("November 30 2005"))
|
35
36
|
)
|
36
|
-
assert_equal
|
37
|
-
token = doc.elements["/OAI-PMH/resumptionToken"].text
|
38
|
-
assert_not_nil doc.elements["/OAI-PMH/resumptionToken"]
|
37
|
+
assert_equal 26, doc.elements["/OAI-PMH/ListRecords"].size
|
38
|
+
token = doc.elements["/OAI-PMH/ListRecords/resumptionToken"].text
|
39
|
+
assert_not_nil doc.elements["/OAI-PMH/ListRecords/resumptionToken"]
|
39
40
|
doc = Document.new(@provider.list_records(:resumption_token => token))
|
40
41
|
assert_equal 25, doc.elements["/OAI-PMH/ListRecords"].size
|
41
|
-
assert_nil doc.elements["/OAI-PMH/resumptionToken"]
|
42
|
+
assert_nil doc.elements["/OAI-PMH/ListRecords/resumptionToken"]
|
42
43
|
end
|
43
44
|
|
44
45
|
def setup
|
@@ -5,42 +5,43 @@ class SimpleResumptionProviderTest < Test::Unit::TestCase
|
|
5
5
|
|
6
6
|
def test_full_harvest
|
7
7
|
doc = Document.new(@provider.list_records)
|
8
|
-
assert_not_nil doc.elements["/OAI-PMH/resumptionToken"]
|
9
|
-
assert_equal
|
10
|
-
token = doc.elements["/OAI-PMH/resumptionToken"].text
|
8
|
+
assert_not_nil doc.elements["/OAI-PMH/ListRecords/resumptionToken"]
|
9
|
+
assert_equal 26, doc.elements["/OAI-PMH/ListRecords"].to_a.size
|
10
|
+
token = doc.elements["/OAI-PMH/ListRecords/resumptionToken"].text
|
11
11
|
doc = Document.new(@provider.list_records(:resumption_token => token))
|
12
|
-
assert_not_nil doc.elements["/OAI-PMH/resumptionToken"]
|
13
|
-
token = doc.elements["/OAI-PMH/resumptionToken"].text
|
14
|
-
assert_equal
|
12
|
+
assert_not_nil doc.elements["/OAI-PMH/ListRecords/resumptionToken"]
|
13
|
+
token = doc.elements["/OAI-PMH/ListRecords/resumptionToken"].text
|
14
|
+
assert_equal 26, doc.elements["/OAI-PMH/ListRecords"].to_a.size
|
15
15
|
doc = Document.new(@provider.list_records(:resumption_token => token))
|
16
|
-
assert_not_nil doc.elements["/OAI-PMH/resumptionToken"]
|
17
|
-
token = doc.elements["/OAI-PMH/resumptionToken"].text
|
18
|
-
assert_equal
|
16
|
+
assert_not_nil doc.elements["/OAI-PMH/ListRecords/resumptionToken"]
|
17
|
+
token = doc.elements["/OAI-PMH/ListRecords/resumptionToken"].text
|
18
|
+
assert_equal 26, doc.elements["/OAI-PMH/ListRecords"].to_a.size
|
19
19
|
doc = Document.new(@provider.list_records(:resumption_token => token))
|
20
|
-
assert_nil doc.elements["/OAI-PMH/resumptionToken"]
|
20
|
+
assert_nil doc.elements["/OAI-PMH/ListRecords/resumptionToken"]
|
21
21
|
assert_equal 25, doc.elements["/OAI-PMH/ListRecords"].to_a.size
|
22
22
|
end
|
23
23
|
|
24
24
|
def test_from_and_until
|
25
|
-
DCField.
|
26
|
-
|
27
|
-
|
28
|
-
|
25
|
+
first_id = DCField.find(:first, :order => "id asc").id
|
26
|
+
DCField.update_all(['updated_at = ?', Time.parse("September 15 2005")],
|
27
|
+
"id < #{first_id + 25}")
|
28
|
+
DCField.update_all(['updated_at = ?', Time.parse("November 1 2005")],
|
29
|
+
"id <= #{first_id + 50} and id > #{first_id + 25}")
|
29
30
|
|
30
|
-
total = DCField.count(:id, :conditions => ["updated_at >= ? AND updated_at <= ?",
|
31
|
+
total = DCField.count(:id, :conditions => ["updated_at >= ? AND updated_at <= ?", Time.parse("September 1 2005"), Time.parse("November 30 2005")])
|
31
32
|
|
32
33
|
# Should return 50 records broken into 2 groups of 25.
|
33
34
|
doc = Document.new(
|
34
35
|
@provider.list_records(
|
35
|
-
:from =>
|
36
|
-
:until =>
|
36
|
+
:from => Time.parse("September 1 2005"),
|
37
|
+
:until => Time.parse("November 30 2005"))
|
37
38
|
)
|
38
|
-
assert_equal
|
39
|
-
assert_not_nil doc.elements["/OAI-PMH/resumptionToken"]
|
40
|
-
token = doc.elements["/OAI-PMH/resumptionToken"].text
|
39
|
+
assert_equal 26, doc.elements["/OAI-PMH/ListRecords"].to_a.size
|
40
|
+
assert_not_nil doc.elements["/OAI-PMH/ListRecords/resumptionToken"]
|
41
|
+
token = doc.elements["/OAI-PMH/ListRecords/resumptionToken"].text
|
41
42
|
doc = Document.new(@provider.list_records(:resumption_token => token))
|
42
|
-
assert_equal
|
43
|
-
assert_nil doc.elements["/OAI-PMH/resumptionToken"]
|
43
|
+
assert_equal 25, doc.elements["/OAI-PMH/ListRecords"].to_a.size
|
44
|
+
assert_nil doc.elements["/OAI-PMH/ListRecords/resumptionToken"]
|
44
45
|
end
|
45
46
|
|
46
47
|
def setup
|
data/test/client/tc_exception.rb
CHANGED
@@ -2,9 +2,9 @@ require 'test_helper'
|
|
2
2
|
|
3
3
|
class ExceptionTest < Test::Unit::TestCase
|
4
4
|
|
5
|
-
def
|
6
|
-
client = OAI::Client.new 'http://www.
|
7
|
-
assert_raises(
|
5
|
+
def test_not_found
|
6
|
+
client = OAI::Client.new 'http://www.google.com'
|
7
|
+
assert_raises(ArgumentError) { client.identify }
|
8
8
|
end
|
9
9
|
|
10
10
|
def test_xml_error
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class LowResolutionDatesTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def test_low_res_date_parsing
|
6
|
+
client = OAI::Client.new 'http://caltechcstr.library.caltech.edu/perl/oai2'
|
7
|
+
|
8
|
+
date = Date.new 2003, 1, 1
|
9
|
+
|
10
|
+
# get a list of identifier headers
|
11
|
+
assert_nothing_raised { client.list_identifiers :from => date }
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class UTF8Test < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def test_escaping_invalid_utf_8_characters
|
6
|
+
client = OAI::Client.new 'http://localhost:3333/oai' #, :parser => 'libxml'
|
7
|
+
invalid_utf_8 = [2, 3, 4, 104, 5, 101, 6, 108, 66897, 108, 66535, 111, 1114112, 33, 55234123, 33].pack("U*")
|
8
|
+
assert_equal("hello!!", client.send(:strip_invalid_utf_8_chars, invalid_utf_8).gsub(/\?/, ''))
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
data/test/client/tc_xpath.rb
CHANGED
@@ -13,7 +13,7 @@ class XpathTest < Test::Unit::TestCase
|
|
13
13
|
def test_libxml
|
14
14
|
begin
|
15
15
|
require 'xml/libxml'
|
16
|
-
rescue
|
16
|
+
rescue LoadError
|
17
17
|
# libxml not available so nothing to test!
|
18
18
|
return
|
19
19
|
end
|
@@ -23,7 +23,4 @@ class XpathTest < Test::Unit::TestCase
|
|
23
23
|
assert_equal xpath(doc, './/foobar'), nil
|
24
24
|
end
|
25
25
|
|
26
|
-
end
|
27
|
-
|
28
|
-
__END__
|
29
|
-
|
26
|
+
end
|
data/test/provider/models.rb
CHANGED
@@ -143,9 +143,9 @@ class SimpleModel < TestModel
|
|
143
143
|
set_two.spec = "A:B"
|
144
144
|
set_two.description = "This is test set two."
|
145
145
|
|
146
|
-
generate_records(5,
|
147
|
-
generate_records(1,
|
148
|
-
generate_records(4,
|
146
|
+
generate_records(5, Time.parse("2002-10-5"), set_one)
|
147
|
+
generate_records(1, Time.parse("2002-11-5"), [set_two], true)
|
148
|
+
generate_records(4, Time.parse("2002-11-5"), [set_two])
|
149
149
|
end
|
150
150
|
|
151
151
|
end
|
@@ -154,11 +154,11 @@ class BigModel < TestModel
|
|
154
154
|
|
155
155
|
def initialize(limit = nil)
|
156
156
|
super(limit)
|
157
|
-
generate_records(100,
|
158
|
-
generate_records(100,
|
159
|
-
generate_records(100,
|
160
|
-
generate_records(100,
|
161
|
-
generate_records(100,
|
157
|
+
generate_records(100, Time.parse("October 2 2000"))
|
158
|
+
generate_records(100, Time.parse("November 2 2000"))
|
159
|
+
generate_records(100, Time.parse("December 2 2000"))
|
160
|
+
generate_records(100, Time.parse("January 2 2001"))
|
161
|
+
generate_records(100, Time.parse("February 2 2001"))
|
162
162
|
end
|
163
163
|
|
164
164
|
end
|
@@ -172,7 +172,7 @@ class MappedModel < TestModel
|
|
172
172
|
set_one.spec = "A"
|
173
173
|
set_one.description = "This is test set one."
|
174
174
|
|
175
|
-
generate_records(5,
|
175
|
+
generate_records(5, Time.parse("dec 1 2006"), set_one)
|
176
176
|
end
|
177
177
|
|
178
178
|
def map_oai_dc
|
@@ -216,14 +216,14 @@ class ComplexModel < TestModel
|
|
216
216
|
set_three_four.spec = "Three:Four"
|
217
217
|
set_three_four.description = "This is combination set of Three and Four."
|
218
218
|
|
219
|
-
generate_records(250,
|
220
|
-
generate_records(50,
|
221
|
-
generate_records(50,
|
222
|
-
generate_records(250,
|
219
|
+
generate_records(250, Time.parse("May 2 1998"), [set_one, set_one_two])
|
220
|
+
generate_records(50, Time.parse("June 2 1998"), [set_one, set_one_two], true)
|
221
|
+
generate_records(50, Time.parse("October 10 1998"), [set_three, set_three_four], true)
|
222
|
+
generate_records(250, Time.parse("July 2 2002"), [set_two, set_one_two])
|
223
223
|
|
224
|
-
generate_records(250,
|
225
|
-
generate_records(50,
|
226
|
-
generate_records(250,
|
224
|
+
generate_records(250, Time.parse("September 15 2004"), [set_three, set_three_four])
|
225
|
+
generate_records(50, Time.parse("October 10 2004"), [set_three, set_three_four], true)
|
226
|
+
generate_records(250, Time.parse("December 25 2005"), [set_four, set_three_four])
|
227
227
|
end
|
228
228
|
|
229
229
|
end
|
@@ -1,7 +1,8 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
3
|
class ProviderExceptions < Test::Unit::TestCase
|
4
|
-
|
4
|
+
include Singleton
|
5
|
+
|
5
6
|
def setup
|
6
7
|
@provider = ComplexProvider.new
|
7
8
|
end
|
@@ -51,8 +52,8 @@ class ProviderExceptions < Test::Unit::TestCase
|
|
51
52
|
|
52
53
|
def test_no_records_match_dates_that_are_out_of_range
|
53
54
|
assert_raise(OAI::NoMatchException) do
|
54
|
-
@provider.list_records(:from =>
|
55
|
-
:until =>
|
55
|
+
@provider.list_records(:from => Time.parse("November 2 2000"),
|
56
|
+
:until => Time.parse("November 1 2000"))
|
56
57
|
end
|
57
58
|
end
|
58
59
|
|
@@ -23,8 +23,8 @@ class ResumptionTokenFunctionalTest < Test::Unit::TestCase
|
|
23
23
|
assert_nothing_raised { Document.new(@provider.list_records) }
|
24
24
|
doc = Document.new(
|
25
25
|
@provider.list_records(
|
26
|
-
:from =>
|
27
|
-
:until =>
|
26
|
+
:from => Time.parse("September 1 2004"),
|
27
|
+
:until => Time.parse("November 30 2004"))
|
28
28
|
)
|
29
29
|
assert_equal 101, doc.elements["/OAI-PMH/ListRecords"].to_a.size
|
30
30
|
token = doc.elements["/OAI-PMH/ListRecords/resumptionToken"].text
|
@@ -33,12 +33,12 @@ class OaiTest < Test::Unit::TestCase
|
|
33
33
|
def test_from
|
34
34
|
assert_nothing_raised { REXML::Document.new(@big_provider.list_records) }
|
35
35
|
doc = REXML::Document.new(
|
36
|
-
@big_provider.list_records(:from =>
|
36
|
+
@big_provider.list_records(:from => Time.parse("February 1 2001"))
|
37
37
|
)
|
38
38
|
assert_equal 100, doc.elements['OAI-PMH/ListRecords'].to_a.size
|
39
39
|
|
40
40
|
doc = REXML::Document.new(
|
41
|
-
@big_provider.list_records(:from =>
|
41
|
+
@big_provider.list_records(:from => Time.parse("January 1 2001"))
|
42
42
|
)
|
43
43
|
assert_equal 200, doc.elements['OAI-PMH/ListRecords'].to_a.size
|
44
44
|
end
|
@@ -46,7 +46,7 @@ class OaiTest < Test::Unit::TestCase
|
|
46
46
|
def test_until
|
47
47
|
assert_nothing_raised { REXML::Document.new(@big_provider.list_records) }
|
48
48
|
doc = REXML::Document.new(
|
49
|
-
@big_provider.list_records(:until =>
|
49
|
+
@big_provider.list_records(:until => Time.parse("November 1 2000"))
|
50
50
|
)
|
51
51
|
assert_equal 100, doc.elements['OAI-PMH/ListRecords'].to_a.size
|
52
52
|
end
|
@@ -54,14 +54,14 @@ class OaiTest < Test::Unit::TestCase
|
|
54
54
|
def test_from_and_until
|
55
55
|
assert_nothing_raised { REXML::Document.new(@big_provider.list_records) }
|
56
56
|
doc = REXML::Document.new(
|
57
|
-
@big_provider.list_records(:from =>
|
58
|
-
:until =>
|
57
|
+
@big_provider.list_records(:from => Time.parse("November 1 2000"),
|
58
|
+
:until => Time.parse("November 30 2000"))
|
59
59
|
)
|
60
60
|
assert_equal 100, doc.elements['OAI-PMH/ListRecords'].to_a.size
|
61
61
|
|
62
62
|
doc = REXML::Document.new(
|
63
|
-
@big_provider.list_records(:from =>
|
64
|
-
:until =>
|
63
|
+
@big_provider.list_records(:from => Time.parse("December 1 2000"),
|
64
|
+
:until => Time.parse("December 31 2000"))
|
65
65
|
)
|
66
66
|
assert_equal 100, doc.elements['OAI-PMH/ListRecords'].to_a.size
|
67
67
|
end
|
metadata
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
|
-
rubygems_version: 0.9.
|
2
|
+
rubygems_version: 0.9.4
|
3
3
|
specification_version: 1
|
4
4
|
name: oai
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.0.
|
7
|
-
date:
|
6
|
+
version: 0.0.7
|
7
|
+
date: 2008-01-14 00:00:00 -05:00
|
8
8
|
summary: A ruby library for working with the Open Archive Initiative Protocol for Metadata Harvesting (OAI-PMH)
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -33,30 +33,30 @@ files:
|
|
33
33
|
- Rakefile
|
34
34
|
- bin/oai
|
35
35
|
- test/activerecord_provider
|
36
|
-
- test/client
|
37
|
-
- test/provider
|
38
|
-
- test/test.xml
|
39
36
|
- test/activerecord_provider/config
|
40
|
-
- test/activerecord_provider/database
|
41
|
-
- test/activerecord_provider/fixtures
|
42
|
-
- test/activerecord_provider/helpers
|
43
|
-
- test/activerecord_provider/models
|
44
|
-
- test/activerecord_provider/tc_ar_provider.rb
|
45
|
-
- test/activerecord_provider/tc_ar_sets_provider.rb
|
46
|
-
- test/activerecord_provider/tc_caching_paging_provider.rb
|
47
|
-
- test/activerecord_provider/tc_simple_paging_provider.rb
|
48
|
-
- test/activerecord_provider/test_helper.rb
|
49
37
|
- test/activerecord_provider/config/connection.rb
|
50
38
|
- test/activerecord_provider/config/database.yml
|
39
|
+
- test/activerecord_provider/database
|
51
40
|
- test/activerecord_provider/database/ar_migration.rb
|
52
41
|
- test/activerecord_provider/database/oaipmhtest
|
42
|
+
- test/activerecord_provider/fixtures
|
53
43
|
- test/activerecord_provider/fixtures/dc.yml
|
44
|
+
- test/activerecord_provider/helpers
|
54
45
|
- test/activerecord_provider/helpers/providers.rb
|
55
46
|
- test/activerecord_provider/helpers/set_provider.rb
|
47
|
+
- test/activerecord_provider/models
|
56
48
|
- test/activerecord_provider/models/dc_field.rb
|
57
49
|
- test/activerecord_provider/models/dc_set.rb
|
58
50
|
- test/activerecord_provider/models/oai_token.rb
|
51
|
+
- test/activerecord_provider/tc_ar_provider.rb
|
52
|
+
- test/activerecord_provider/tc_ar_sets_provider.rb
|
53
|
+
- test/activerecord_provider/tc_caching_paging_provider.rb
|
54
|
+
- test/activerecord_provider/tc_simple_paging_provider.rb
|
55
|
+
- test/activerecord_provider/test_helper.rb
|
56
|
+
- test/client
|
59
57
|
- test/client/helpers
|
58
|
+
- test/client/helpers/provider.rb
|
59
|
+
- test/client/helpers/test_wrapper.rb
|
60
60
|
- test/client/tc_exception.rb
|
61
61
|
- test/client/tc_get_record.rb
|
62
62
|
- test/client/tc_identify.rb
|
@@ -65,10 +65,11 @@ files:
|
|
65
65
|
- test/client/tc_list_metadata_formats.rb
|
66
66
|
- test/client/tc_list_records.rb
|
67
67
|
- test/client/tc_list_sets.rb
|
68
|
+
- test/client/tc_low_resolution_dates.rb
|
69
|
+
- test/client/tc_utf8_escaping.rb
|
68
70
|
- test/client/tc_xpath.rb
|
69
71
|
- test/client/test_helper.rb
|
70
|
-
- test/
|
71
|
-
- test/client/helpers/test_wrapper.rb
|
72
|
+
- test/provider
|
72
73
|
- test/provider/models.rb
|
73
74
|
- test/provider/tc_exceptions.rb
|
74
75
|
- test/provider/tc_functional_tokens.rb
|
@@ -76,19 +77,9 @@ files:
|
|
76
77
|
- test/provider/tc_resumption_tokens.rb
|
77
78
|
- test/provider/tc_simple_provider.rb
|
78
79
|
- test/provider/test_helper.rb
|
80
|
+
- test/test.xml
|
79
81
|
- lib/oai
|
80
|
-
- lib/oai.rb
|
81
|
-
- lib/test.rb
|
82
82
|
- lib/oai/client
|
83
|
-
- lib/oai/client.rb
|
84
|
-
- lib/oai/constants.rb
|
85
|
-
- lib/oai/exception.rb
|
86
|
-
- lib/oai/harvester
|
87
|
-
- lib/oai/harvester.rb
|
88
|
-
- lib/oai/provider
|
89
|
-
- lib/oai/provider.rb
|
90
|
-
- lib/oai/set.rb
|
91
|
-
- lib/oai/xpath.rb
|
92
83
|
- lib/oai/client/get_record.rb
|
93
84
|
- lib/oai/client/header.rb
|
94
85
|
- lib/oai/client/identify.rb
|
@@ -99,23 +90,27 @@ files:
|
|
99
90
|
- lib/oai/client/metadata_format.rb
|
100
91
|
- lib/oai/client/record.rb
|
101
92
|
- lib/oai/client/response.rb
|
93
|
+
- lib/oai/client.rb
|
94
|
+
- lib/oai/constants.rb
|
95
|
+
- lib/oai/exception.rb
|
96
|
+
- lib/oai/harvester
|
102
97
|
- lib/oai/harvester/config.rb
|
103
98
|
- lib/oai/harvester/harvest.rb
|
104
99
|
- lib/oai/harvester/logging.rb
|
105
100
|
- lib/oai/harvester/mailer.rb
|
106
101
|
- lib/oai/harvester/shell.rb
|
102
|
+
- lib/oai/harvester.rb
|
103
|
+
- lib/oai/provider
|
107
104
|
- lib/oai/provider/extensions
|
108
105
|
- lib/oai/provider/metadata_format
|
106
|
+
- lib/oai/provider/metadata_format/oai_dc.rb
|
109
107
|
- lib/oai/provider/metadata_format.rb
|
110
108
|
- lib/oai/provider/model
|
109
|
+
- lib/oai/provider/model/activerecord_caching_wrapper.rb
|
110
|
+
- lib/oai/provider/model/activerecord_wrapper.rb
|
111
111
|
- lib/oai/provider/model.rb
|
112
112
|
- lib/oai/provider/partial_result.rb
|
113
113
|
- lib/oai/provider/response
|
114
|
-
- lib/oai/provider/response.rb
|
115
|
-
- lib/oai/provider/resumption_token.rb
|
116
|
-
- lib/oai/provider/metadata_format/oai_dc.rb
|
117
|
-
- lib/oai/provider/model/activerecord_caching_wrapper.rb
|
118
|
-
- lib/oai/provider/model/activerecord_wrapper.rb
|
119
114
|
- lib/oai/provider/response/error.rb
|
120
115
|
- lib/oai/provider/response/get_record.rb
|
121
116
|
- lib/oai/provider/response/identify.rb
|
@@ -124,6 +119,13 @@ files:
|
|
124
119
|
- lib/oai/provider/response/list_records.rb
|
125
120
|
- lib/oai/provider/response/list_sets.rb
|
126
121
|
- lib/oai/provider/response/record_response.rb
|
122
|
+
- lib/oai/provider/response.rb
|
123
|
+
- lib/oai/provider/resumption_token.rb
|
124
|
+
- lib/oai/provider.rb
|
125
|
+
- lib/oai/set.rb
|
126
|
+
- lib/oai/xpath.rb
|
127
|
+
- lib/oai.rb
|
128
|
+
- lib/test.rb
|
127
129
|
- examples/models/file_model.rb
|
128
130
|
- examples/providers/dublin_core.rb
|
129
131
|
test_files: []
|
@@ -139,24 +141,6 @@ extensions: []
|
|
139
141
|
requirements: []
|
140
142
|
|
141
143
|
dependencies:
|
142
|
-
- !ruby/object:Gem::Dependency
|
143
|
-
name: activesupport
|
144
|
-
version_requirement:
|
145
|
-
version_requirements: !ruby/object:Gem::Version::Requirement
|
146
|
-
requirements:
|
147
|
-
- - ">="
|
148
|
-
- !ruby/object:Gem::Version
|
149
|
-
version: 1.3.1
|
150
|
-
version:
|
151
|
-
- !ruby/object:Gem::Dependency
|
152
|
-
name: chronic
|
153
|
-
version_requirement:
|
154
|
-
version_requirements: !ruby/object:Gem::Version::Requirement
|
155
|
-
requirements:
|
156
|
-
- - ">="
|
157
|
-
- !ruby/object:Gem::Version
|
158
|
-
version: 0.0.3
|
159
|
-
version:
|
160
144
|
- !ruby/object:Gem::Dependency
|
161
145
|
name: builder
|
162
146
|
version_requirement:
|