perennial 0.2.2.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,511 @@
1
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
2
+ require 'fakefs'
3
+ require 'test/unit'
4
+
5
+ class FakeFSTest < Test::Unit::TestCase
6
+ include FakeFS
7
+
8
+ def setup
9
+ FileSystem.clear
10
+ end
11
+
12
+ def test_can_be_initialized_empty
13
+ fs = FileSystem
14
+ assert_equal 0, fs.files.size
15
+ end
16
+
17
+ def xtest_can_be_initialized_with_an_existing_directory
18
+ fs = FileSystem
19
+ fs.clone(File.expand_path(File.dirname(__FILE__))).inspect
20
+ puts fs.files.inspect
21
+ assert_equal 1, fs.files.size
22
+ end
23
+
24
+ def test_can_create_directories
25
+ FileUtils.mkdir_p("/path/to/dir")
26
+ assert_kind_of MockDir, FileSystem.fs['path']['to']['dir']
27
+ end
28
+
29
+ def test_knows_directories_exist
30
+ FileUtils.mkdir_p(path = "/path/to/dir")
31
+ assert File.exists?(path)
32
+ end
33
+
34
+ def test_knows_directories_are_directories
35
+ FileUtils.mkdir_p(path = "/path/to/dir")
36
+ assert File.directory?(path)
37
+ end
38
+
39
+ def test_knows_symlink_directories_are_directories
40
+ FileUtils.mkdir_p(path = "/path/to/dir")
41
+ FileUtils.ln_s path, sympath = '/sympath'
42
+ assert File.directory?(sympath)
43
+ end
44
+
45
+ def test_knows_non_existent_directories_arent_directories
46
+ path = 'does/not/exist/'
47
+ assert_equal RealFile.directory?(path), File.directory?(path)
48
+ end
49
+
50
+ def test_doesnt_overwrite_existing_directories
51
+ FileUtils.mkdir_p(path = "/path/to/dir")
52
+ assert File.exists?(path)
53
+ FileUtils.mkdir_p("/path/to")
54
+ assert File.exists?(path)
55
+ end
56
+
57
+ def test_can_create_symlinks
58
+ FileUtils.mkdir_p(target = "/path/to/target")
59
+ FileUtils.ln_s(target, "/path/to/link")
60
+ assert_kind_of MockSymlink, FileSystem.fs['path']['to']['link']
61
+
62
+ assert_raises(Errno::EEXIST) {
63
+ FileUtils.ln_s(target, '/path/to/link')
64
+ }
65
+ end
66
+
67
+ def test_can_follow_symlinks
68
+ FileUtils.mkdir_p(target = "/path/to/target")
69
+ FileUtils.ln_s(target, link = "/path/to/symlink")
70
+ assert_equal target, File.readlink(link)
71
+ end
72
+
73
+ def test_knows_symlinks_are_symlinks
74
+ FileUtils.mkdir_p(target = "/path/to/target")
75
+ FileUtils.ln_s(target, link = "/path/to/symlink")
76
+ assert File.symlink?(link)
77
+ end
78
+
79
+ def test_can_create_files
80
+ path = '/path/to/file.txt'
81
+ File.open(path, 'w') do |f|
82
+ f.write "Yatta!"
83
+ end
84
+
85
+ assert File.exists?(path)
86
+ end
87
+
88
+ def test_can_read_files_once_written
89
+ path = '/path/to/file.txt'
90
+ File.open(path, 'w') do |f|
91
+ f.write "Yatta!"
92
+ end
93
+
94
+ assert_equal "Yatta!", File.read(path)
95
+ end
96
+
97
+ def test_can_write_to_files
98
+ path = '/path/to/file.txt'
99
+ File.open(path, 'w') do |f|
100
+ f << 'Yada Yada'
101
+ end
102
+ assert_equal 'Yada Yada', File.read(path)
103
+ end
104
+
105
+ def test_can_read_with_File_readlines
106
+ path = '/path/to/file.txt'
107
+ File.open(path, 'w') do |f|
108
+ f.puts "Yatta!"
109
+ f.puts "woot"
110
+ end
111
+
112
+ assert_equal ["Yatta!", "woot"], File.readlines(path)
113
+ end
114
+
115
+ def test_File_close_disallows_further_access
116
+ path = '/path/to/file.txt'
117
+ file = File.open(path, 'w')
118
+ file.write 'Yada'
119
+ file.close
120
+ assert_raise IOError do
121
+ file.read
122
+ end
123
+ end
124
+
125
+ def test_can_read_from_file_objects
126
+ path = '/path/to/file.txt'
127
+ File.open(path, 'w') do |f|
128
+ f.write "Yatta!"
129
+ end
130
+
131
+ assert_equal "Yatta!", File.new(path).read
132
+ end
133
+
134
+ def test_file_read_errors_appropriately
135
+ assert_raise Errno::ENOENT do
136
+ File.read('anything')
137
+ end
138
+ end
139
+
140
+ def test_knows_files_are_files
141
+ path = '/path/to/file.txt'
142
+ File.open(path, 'w') do |f|
143
+ f.write "Yatta!"
144
+ end
145
+
146
+ assert File.file?(path)
147
+ end
148
+
149
+ def test_knows_symlink_files_are_files
150
+ path = '/path/to/file.txt'
151
+ File.open(path, 'w') do |f|
152
+ f.write "Yatta!"
153
+ end
154
+ FileUtils.ln_s path, sympath='/sympath'
155
+
156
+ assert File.file?(sympath)
157
+ end
158
+
159
+ def test_knows_non_existent_files_arent_files
160
+ assert_equal RealFile.file?('does/not/exist.txt'), File.file?('does/not/exist.txt')
161
+ end
162
+
163
+ def test_can_chown_files
164
+ good = 'file.txt'
165
+ bad = 'nofile.txt'
166
+ File.open(good,'w'){|f| f.write "foo" }
167
+
168
+ assert_equal [good], FileUtils.chown('noone', 'nogroup', good, :verbose => true)
169
+ assert_raises(Errno::ENOENT) do
170
+ FileUtils.chown('noone', 'nogroup', bad, :verbose => true)
171
+ end
172
+
173
+ assert_equal [good], FileUtils.chown('noone', 'nogroup', good)
174
+ assert_raises(Errno::ENOENT) do
175
+ FileUtils.chown('noone', 'nogroup', bad)
176
+ end
177
+
178
+ assert_equal [good], FileUtils.chown('noone', 'nogroup', [good])
179
+ assert_raises(Errno::ENOENT) do
180
+ FileUtils.chown('noone', 'nogroup', [good, bad])
181
+ end
182
+ end
183
+
184
+ def test_can_chown_R_files
185
+ FileUtils.mkdir_p '/path/'
186
+ File.open('/path/foo', 'w'){|f| f.write 'foo' }
187
+ File.open('/path/foobar', 'w'){|f| f.write 'foo' }
188
+ resp = FileUtils.chown_R('no', 'no', '/path')
189
+ assert_equal ['/path'], resp
190
+ end
191
+
192
+ def test_dir_globs_paths
193
+ FileUtils.mkdir_p '/path'
194
+ File.open('/path/foo', 'w'){|f| f.write 'foo' }
195
+ File.open('/path/foobar', 'w'){|f| f.write 'foo' }
196
+
197
+ FileUtils.mkdir_p '/path/bar'
198
+ File.open('/path/bar/baz', 'w'){|f| f.write 'foo' }
199
+
200
+ FileUtils.cp_r '/path/bar', '/path/bar2'
201
+
202
+ assert_equal ['/path'], Dir['/path']
203
+ assert_equal %w( /path/bar /path/bar2 /path/foo /path/foobar ), Dir['/path/*']
204
+
205
+ assert_equal ['/path/bar/baz'], Dir['/path/bar/*']
206
+
207
+ # Unsupported so far. More hackery than I want to work on right now
208
+ # assert_equal ['/path'], Dir['/path*']
209
+ end
210
+
211
+ def test_chdir_changes_directories_like_a_boss
212
+ # I know memes!
213
+ FileUtils.mkdir_p '/path'
214
+ assert_equal '.', FileSystem.fs.name
215
+ assert_equal({}, FileSystem.fs['path'])
216
+ Dir.chdir '/path' do
217
+ File.open('foo', 'w'){|f| f.write 'foo'}
218
+ File.open('foobar', 'w'){|f| f.write 'foo'}
219
+ end
220
+
221
+ assert_equal '.', FileSystem.fs.name
222
+ assert_equal(['foo', 'foobar'], FileSystem.fs['path'].keys.sort)
223
+
224
+ c = nil
225
+ Dir.chdir '/path' do
226
+ c = File.open('foo', 'r'){|f| f.read }
227
+ end
228
+
229
+ assert_equal 'foo', c
230
+ end
231
+
232
+ def test_chdir_shouldnt_keep_us_from_absolute_paths
233
+ FileUtils.mkdir_p '/path'
234
+
235
+ Dir.chdir '/path' do
236
+ File.open('foo', 'w'){|f| f.write 'foo'}
237
+ File.open('/foobar', 'w'){|f| f.write 'foo'}
238
+ end
239
+ assert_equal ['foo'], FileSystem.fs['path'].keys.sort
240
+ assert_equal ['foobar', 'path'], FileSystem.fs.keys.sort
241
+
242
+ Dir.chdir '/path' do
243
+ FileUtils.rm('foo')
244
+ FileUtils.rm('/foobar')
245
+ end
246
+
247
+ assert_equal [], FileSystem.fs['path'].keys.sort
248
+ assert_equal ['path'], FileSystem.fs.keys.sort
249
+ end
250
+
251
+ def test_chdir_should_be_nestable
252
+ FileUtils.mkdir_p '/path/me'
253
+ Dir.chdir '/path' do
254
+ File.open('foo', 'w'){|f| f.write 'foo'}
255
+ Dir.chdir 'me' do
256
+ File.open('foobar', 'w'){|f| f.write 'foo'}
257
+ end
258
+ end
259
+
260
+ assert_equal ['foo','me'], FileSystem.fs['path'].keys.sort
261
+ assert_equal ['foobar'], FileSystem.fs['path']['me'].keys.sort
262
+ end
263
+
264
+ def test_chdir_should_flop_over_and_die_if_the_dir_doesnt_exist
265
+ assert_raise(Errno::ENOENT) do
266
+ Dir.chdir('/nope') do
267
+ 1
268
+ end
269
+ end
270
+ end
271
+
272
+ def test_chdir_shouldnt_lose_state_because_of_errors
273
+ FileUtils.mkdir_p '/path'
274
+
275
+ Dir.chdir '/path' do
276
+ File.open('foo', 'w'){|f| f.write 'foo'}
277
+ File.open('foobar', 'w'){|f| f.write 'foo'}
278
+ end
279
+
280
+ begin
281
+ Dir.chdir('/path') do
282
+ raise Exception
283
+ end
284
+ rescue Exception # hardcore
285
+ end
286
+
287
+ Dir.chdir('/path') do
288
+ begin
289
+ Dir.chdir('nope'){ }
290
+ rescue Errno::ENOENT
291
+ end
292
+
293
+ assert_equal ['/path'], FileSystem.dir_levels
294
+ end
295
+
296
+ assert_equal(['foo', 'foobar'], FileSystem.fs['path'].keys.sort)
297
+ end
298
+
299
+ def test_chdir_with_no_block_is_awesome
300
+ FileUtils.mkdir_p '/path'
301
+ Dir.chdir('/path')
302
+ FileUtils.mkdir_p 'subdir'
303
+ assert_equal ['subdir'], FileSystem.current_dir.keys
304
+ Dir.chdir('subdir')
305
+ File.open('foo', 'w'){|f| f.write 'foo'}
306
+ assert_equal ['foo'], FileSystem.current_dir.keys
307
+
308
+ assert_raises(Errno::ENOENT) do
309
+ Dir.chdir('subsubdir')
310
+ end
311
+
312
+ assert_equal ['foo'], FileSystem.current_dir.keys
313
+ end
314
+
315
+ def test_file_open_defaults_to_read
316
+ File.open('foo','w'){|f| f.write 'bar' }
317
+ assert_equal 'bar', File.open('foo'){|f| f.read }
318
+ end
319
+
320
+ def test_flush_exists_on_file
321
+ r = File.open('foo','w'){|f| f.write 'bar'; f.flush }
322
+ assert_equal 'foo', r.path
323
+ end
324
+
325
+ def test_mv_should_raise_error_on_missing_file
326
+ assert_raise(Errno::ENOENT) do
327
+ FileUtils.mv 'blafgag', 'foo'
328
+ end
329
+ end
330
+
331
+ def test_mv_actually_works
332
+ File.open('foo', 'w') {|f| f.write 'bar' }
333
+ FileUtils.mv 'foo', 'baz'
334
+ assert_equal 'bar', File.open('baz'){|f| f.read }
335
+ end
336
+
337
+ def test_cp_actually_works
338
+ File.open('foo', 'w') {|f| f.write 'bar' }
339
+ FileUtils.cp('foo', 'baz')
340
+ assert_equal 'bar', File.read('baz')
341
+ end
342
+
343
+ def test_cp_file_into_dir
344
+ File.open('foo', 'w') {|f| f.write 'bar' }
345
+ FileUtils.mkdir_p 'baz'
346
+
347
+ FileUtils.cp('foo', 'baz')
348
+ assert_equal 'bar', File.read('baz/foo')
349
+ end
350
+
351
+ def test_cp_overwrites_dest_file
352
+ File.open('foo', 'w') {|f| f.write 'FOO' }
353
+ File.open('bar', 'w') {|f| f.write 'BAR' }
354
+
355
+ FileUtils.cp('foo', 'bar')
356
+ assert_equal 'FOO', File.read('bar')
357
+ end
358
+
359
+ def test_cp_fails_on_no_source
360
+ assert_raise Errno::ENOENT do
361
+ FileUtils.cp('foo', 'baz')
362
+ end
363
+ end
364
+
365
+ def test_cp_fails_on_directory_copy
366
+ FileUtils.mkdir_p 'baz'
367
+
368
+ assert_raise Errno::EISDIR do
369
+ FileUtils.cp('baz', 'bar')
370
+ end
371
+ end
372
+
373
+ def test_cp_r_doesnt_tangle_files_together
374
+ File.open('foo', 'w') {|f| f.write 'bar' }
375
+ FileUtils.cp_r('foo', 'baz')
376
+ File.open('baz', 'w') {|f| f.write 'quux' }
377
+ assert_equal 'bar', File.open('foo'){|f| f.read }
378
+ end
379
+
380
+ def test_cp_r_should_raise_error_on_missing_file
381
+ # Yes, this error sucks, but it conforms to the original Ruby
382
+ # method.
383
+ assert_raise(RuntimeError) do
384
+ FileUtils.cp_r 'blafgag', 'foo'
385
+ end
386
+ end
387
+
388
+ def test_cp_r_handles_copying_directories
389
+ FileUtils.mkdir_p 'subdir'
390
+ Dir.chdir('subdir'){ File.open('foo', 'w'){|f| f.write 'footext' } }
391
+
392
+ FileUtils.mkdir_p 'baz'
393
+
394
+ # To a previously uncreated directory
395
+ FileUtils.cp_r('subdir', 'quux')
396
+ assert_equal 'footext', File.open('quux/foo'){|f| f.read }
397
+
398
+ # To a directory that already exists
399
+ FileUtils.cp_r('subdir', 'baz')
400
+ assert_equal 'footext', File.open('baz/subdir/foo'){|f| f.read }
401
+
402
+ # To a subdirectory of a directory that does not exist
403
+ assert_raises(Errno::ENOENT) {
404
+ FileUtils.cp_r('subdir', 'nope/something')
405
+ }
406
+ end
407
+
408
+ def test_cp_r_only_copies_into_directories
409
+ FileUtils.mkdir_p 'subdir'
410
+ Dir.chdir('subdir'){ File.open('foo', 'w'){|f| f.write 'footext' } }
411
+
412
+ File.open('bar', 'w') {|f| f.write 'bartext' }
413
+
414
+ assert_raises(Errno::EEXIST) do
415
+ FileUtils.cp_r 'subdir', 'bar'
416
+ end
417
+
418
+ FileUtils.mkdir_p 'otherdir'
419
+ FileUtils.ln_s 'otherdir', 'symdir'
420
+
421
+ FileUtils.cp_r 'subdir', 'symdir'
422
+ assert_equal 'footext', File.open('symdir/subdir/foo'){|f| f.read }
423
+ end
424
+
425
+ def test_cp_r_sets_parent_correctly
426
+ FileUtils.mkdir_p '/path/foo'
427
+ File.open('/path/foo/bar', 'w'){|f| f.write 'foo' }
428
+ File.open('/path/foo/baz', 'w'){|f| f.write 'foo' }
429
+
430
+ FileUtils.cp_r '/path/foo', '/path/bar'
431
+
432
+ assert File.exists?('/path/bar/baz')
433
+ FileUtils.rm_rf '/path/bar/baz'
434
+ assert_equal %w( /path/bar/bar ), Dir['/path/bar/*']
435
+ end
436
+
437
+ def test_clone_clones_normal_files
438
+ RealFile.open(here('foo'), 'w'){|f| f.write 'bar' }
439
+ assert !File.exists?(here('foo'))
440
+ FileSystem.clone(here('foo'))
441
+ assert_equal 'bar', File.open(here('foo')){|f| f.read }
442
+ ensure
443
+ RealFile.unlink(here('foo')) if RealFile.exists?(here('foo'))
444
+ end
445
+
446
+ def test_clone_clones_directories
447
+ RealFileUtils.mkdir_p(here('subdir'))
448
+
449
+ FileSystem.clone(here('subdir'))
450
+
451
+ assert File.exists?(here('subdir')), 'subdir was cloned'
452
+ assert File.directory?(here('subdir')), 'subdir is a directory'
453
+ ensure
454
+ RealFileUtils.rm_rf(here('subdir')) if RealFile.exists?(here('subdir'))
455
+ end
456
+
457
+ def test_clone_clones_dot_files_even_hard_to_find_ones
458
+ RealFileUtils.mkdir_p(here('subdir/.bar/baz/.quux/foo'))
459
+ assert !File.exists?(here('subdir'))
460
+
461
+ FileSystem.clone(here('subdir'))
462
+ assert_equal ['.bar'], FileSystem.find(here('subdir')).keys
463
+ assert_equal ['foo'], FileSystem.find(here('subdir/.bar/baz/.quux')).keys
464
+ ensure
465
+ RealFileUtils.rm_rf(here('subdir')) if RealFile.exists?(here('subdir'))
466
+ end
467
+
468
+ def test_putting_a_dot_at_end_copies_the_contents
469
+ FileUtils.mkdir_p 'subdir'
470
+ Dir.chdir('subdir'){ File.open('foo', 'w'){|f| f.write 'footext' } }
471
+
472
+ FileUtils.mkdir_p 'newdir'
473
+ FileUtils.cp_r 'subdir/.', 'newdir'
474
+ assert_equal 'footext', File.open('newdir/foo'){|f| f.read }
475
+ end
476
+
477
+ def test_file_can_read_from_symlinks
478
+ File.open('first', 'w'){|f| f.write '1'}
479
+ FileUtils.ln_s 'first', 'one'
480
+ assert_equal '1', File.open('one'){|f| f.read }
481
+
482
+ FileUtils.mkdir_p 'subdir'
483
+ File.open('subdir/nother','w'){|f| f.write 'works' }
484
+ FileUtils.ln_s 'subdir', 'new'
485
+ assert_equal 'works', File.open('new/nother'){|f| f.read }
486
+ end
487
+
488
+ def test_files_can_be_touched
489
+ FileUtils.touch('touched_file')
490
+ assert File.exists?('touched_file')
491
+ list = ['newfile', 'another']
492
+ FileUtils.touch(list)
493
+ list.each { |fp| assert(File.exists?(fp)) }
494
+ end
495
+
496
+ def test_touch_does_not_work_if_the_dir_path_cannot_be_found
497
+ assert_raises(Errno::ENOENT) {
498
+ FileUtils.touch('this/path/should/not/be/here')
499
+ }
500
+ FileUtils.mkdir_p('subdir')
501
+ list = ['subdir/foo', 'nosubdir/bar']
502
+
503
+ assert_raises(Errno::ENOENT) {
504
+ FileUtils.touch(list)
505
+ }
506
+ end
507
+
508
+ def here(fname)
509
+ RealFile.expand_path(RealFile.dirname(__FILE__)+'/'+fname)
510
+ end
511
+ end
@@ -0,0 +1,27 @@
1
+ # Figure out what's missing from fakefs
2
+ #
3
+ # USAGE
4
+ #
5
+ # $ ruby test/verify.rb | grep "not implemented"
6
+ require 'fakefs'
7
+ require 'test/unit'
8
+
9
+ class FakeFSVerifierTest < Test::Unit::TestCase
10
+ (RealFile.methods - Class.new.methods).each do |name|
11
+ define_method("test #{name} class method") do
12
+ assert File.respond_to?(name), "File.#{name} not implemented"
13
+ end
14
+ end
15
+
16
+ (RealFile.instance_methods - Enumerable.instance_methods).each do |name|
17
+ define_method("test #{name} instance method") do
18
+ assert File.instance_methods.include?(name), "File##{name} not implemented"
19
+ end
20
+ end
21
+
22
+ (RealFileUtils.methods - Class.new.methods).each do |name|
23
+ define_method("test #{name} module method") do
24
+ assert FileUtils.respond_to?(name), "FileUtils.#{name} not implemented"
25
+ end
26
+ end
27
+ end
metadata ADDED
@@ -0,0 +1,92 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: perennial
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.2.2
5
+ platform: ruby
6
+ authors:
7
+ - Darcy Laycock
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-08-09 00:00:00 +08:00
13
+ default_executable: perennial
14
+ dependencies: []
15
+
16
+ description: Perennial is a platform for building different applications in Ruby. It uses a controller-based approach with mixins to provide different functionality.
17
+ email: sutto@sutto.net
18
+ executables:
19
+ - perennial
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - bin/perennial
26
+ - vendor/fakefs/lib/fakefs.rb
27
+ - vendor/fakefs/LICENSE
28
+ - vendor/fakefs/Rakefile
29
+ - vendor/fakefs/README.markdown
30
+ - vendor/fakefs/test/fakefs_test.rb
31
+ - vendor/fakefs/test/verify.rb
32
+ - lib/perennial/application.rb
33
+ - lib/perennial/argument_parser.rb
34
+ - lib/perennial/core_ext/attribute_accessors.rb
35
+ - lib/perennial/core_ext/blank.rb
36
+ - lib/perennial/core_ext/misc.rb
37
+ - lib/perennial/core_ext.rb
38
+ - lib/perennial/daemon.rb
39
+ - lib/perennial/dispatchable.rb
40
+ - lib/perennial/exceptions.rb
41
+ - lib/perennial/generator.rb
42
+ - lib/perennial/hookable.rb
43
+ - lib/perennial/loader.rb
44
+ - lib/perennial/loggable.rb
45
+ - lib/perennial/logger.rb
46
+ - lib/perennial/manifest.rb
47
+ - lib/perennial/option_parser.rb
48
+ - lib/perennial/settings.rb
49
+ - lib/perennial.rb
50
+ - test/dispatchable_test.rb
51
+ - test/hookable_test.rb
52
+ - test/loader_test.rb
53
+ - test/loggable_test.rb
54
+ - test/logger_test.rb
55
+ - test/settings_test.rb
56
+ - test/test_helper.rb
57
+ - templates/application.erb
58
+ - templates/boot.erb
59
+ - templates/rakefile.erb
60
+ - templates/setup.erb
61
+ - templates/test.erb
62
+ - templates/test_helper.erb
63
+ has_rdoc: true
64
+ homepage: http://sutto.net/
65
+ licenses: []
66
+
67
+ post_install_message:
68
+ rdoc_options: []
69
+
70
+ require_paths:
71
+ - lib
72
+ required_ruby_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: "0"
77
+ version:
78
+ required_rubygems_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: "0"
83
+ version:
84
+ requirements: []
85
+
86
+ rubyforge_project:
87
+ rubygems_version: 1.3.5
88
+ signing_key:
89
+ specification_version: 3
90
+ summary: A simple (generally event-oriented) application library for Ruby
91
+ test_files: []
92
+