ThiagoLelis-backgroundjob 1.0.3 → 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,51 @@
1
+ module Main
2
+ ### because active_record fubars the hell out of Logger ;-(
3
+ class Logger < ::Logger
4
+ def self.new *a, &b
5
+ super(*a, &b).instance_eval{ @default_formatter = @formatter = Formatter.new; self }
6
+ end
7
+ def format_message(severity, datetime, progname, msg)
8
+ (@formatter || @default_formatter).call(severity, datetime, progname, msg)
9
+ end
10
+
11
+ def device
12
+ @logdev.instance_eval{ @dev }
13
+ end
14
+
15
+ def tty?
16
+ device.respond_to?('tty?') and device.tty?
17
+ end
18
+
19
+ def turn which
20
+ @logdev.extend OnOff unless OnOff === @logdev
21
+ @logdev.turn which
22
+ end
23
+
24
+ def on
25
+ turn :on
26
+ end
27
+ alias_method "on!", "on"
28
+ def self.on *a, &b
29
+ new(*a, &b).instance_eval{ turn :on; self }
30
+ end
31
+
32
+ def off
33
+ turn :off
34
+ end
35
+ alias_method "off!", "off"
36
+ def self.off *a, &b
37
+ new(*a, &b).instance_eval{ turn :off; self }
38
+ end
39
+
40
+ module OnOff
41
+ def turn which
42
+ @turned = which.to_s =~ %r/on/i ? :on : :off
43
+ end
44
+
45
+ def write message
46
+ return message.to_s.size if @turned == :off
47
+ super
48
+ end
49
+ end
50
+ end
51
+ end
data/lib/main/mode.rb ADDED
@@ -0,0 +1,42 @@
1
+ class Mode < ::String
2
+ class Error < ::StandardError; end
3
+ class Duplicate < Error; end
4
+ class Ambiguous < Error
5
+ include Main::Softspoken
6
+ end
7
+
8
+ class List < ::Array
9
+ def initialize *a, &b
10
+ super
11
+ ensure
12
+ self.fields = []
13
+ end
14
+ def add klass
15
+ mode_name = Mode.new klass.mode_name
16
+ raise Duplicate, mode_name if has_key? mode_name
17
+ self[mode_name] = klass
18
+ end
19
+ def find_by_mode m, options = {}
20
+ quiet = options['quiet'] || options[:quiet]
21
+ each_pair do |mode, klass|
22
+ return mode if mode == m
23
+ end
24
+ candidates = []
25
+ each_pair do |mode, klass|
26
+ candidates << mode if mode.index(m) == 0
27
+ end
28
+ case candidates.size
29
+ when 0
30
+ nil
31
+ when 1
32
+ candidates.first
33
+ else
34
+ raise Ambiguous, "ambiguous mode: #{ m } = (#{ candidates.sort.join ' or ' })?"
35
+ end
36
+ end
37
+ end
38
+
39
+ def self.list *a, &b
40
+ List.new *a, &b
41
+ end
42
+ end
@@ -0,0 +1,685 @@
1
+ module Main
2
+ class Parameter
3
+ class Error < StandardError
4
+ include Softspoken
5
+ fattr 'wrapped'
6
+ end
7
+ class Arity < Error; end
8
+ class NotGiven < Arity; end
9
+ class InValid < Error; end
10
+ class NoneSuch < Error; end
11
+ class AmbigousOption < Error; end
12
+ class NeedlessArgument < Error; end
13
+ class MissingArgument < Error; end
14
+ class InvalidOption < Error; end
15
+
16
+ class << self
17
+ def wrapped_error w
18
+ e = Error.new "(#{ w.message } (#{ w.class }))"
19
+ e.wrapped = w
20
+ e.set_backtrace(w.backtrace || [])
21
+ e
22
+ end
23
+
24
+ def wrap_errors
25
+ begin
26
+ yield
27
+ rescue => e
28
+ raise wrapped_error(e)
29
+ end
30
+ end
31
+
32
+ Types = [ Parameter ]
33
+ def inherited other
34
+ Types << other
35
+ end
36
+
37
+ def sym
38
+ @sym ||= name.split(%r/::/).last.downcase.to_sym
39
+ end
40
+
41
+ def class_for type
42
+ sym = type.to_s.downcase.to_sym
43
+ c = Types.detect{|t| t.sym == sym}
44
+ raise ArgumentError, type.inspect unless c
45
+ c
46
+ end
47
+
48
+ def create type, *a, &b
49
+ c = class_for type
50
+ obj = c.allocate
51
+ obj.type = c.sym
52
+ obj.instance_eval{ initialize *a, &b }
53
+ obj
54
+ end
55
+ end
56
+
57
+ fattr 'type'
58
+ fattr 'names'
59
+ fattr 'abbreviations'
60
+ fattr 'argument'
61
+ fattr 'given'
62
+ fattr 'cast'
63
+ fattr 'validate'
64
+ fattr 'description'
65
+ fattr 'synopsis'
66
+ fattr('values'){ [] }
67
+ fattr('defaults'){ [] }
68
+ fattr('examples'){ [] }
69
+
70
+ fattr 'arity' => 1
71
+ fattr 'required' => false
72
+
73
+ fattr 'error_handler_before'
74
+ fattr 'error_handler_instead'
75
+ fattr 'error_handler_after'
76
+
77
+ def initialize name, *names, &block
78
+ @names = Cast.list_of_string name, *names
79
+ @names.map! do |name|
80
+ if name =~ %r/^-+/
81
+ name.gsub! %r/^-+/, ''
82
+ end
83
+
84
+ if name =~ %r/=.*$/
85
+ argument( name =~ %r/=\s*\[.*$/ ? :optional : :required )
86
+ name.gsub! %r/=.*$/, ''
87
+ end
88
+
89
+ name
90
+ end
91
+ @names = @names.sort.reverse
92
+ @names[1..-1].each do |name|
93
+ raise ArgumentError, "only one long name allowed (#{ @names.inspect })" if
94
+ name.size > 1
95
+ end
96
+
97
+ DSL.evaluate(self, &block) if block
98
+ sanity_check!
99
+ end
100
+
101
+ def sanity_check!
102
+ raise Arity, "#{ name } with arity -1 (zero or more args) cannot be required" if(arity == -1 and required?)
103
+ end
104
+
105
+ def name
106
+ names.first
107
+ end
108
+
109
+ def default
110
+ defaults.first
111
+ end
112
+
113
+ def typename
114
+ prefix = '--' if type.to_s =~ %r/option/
115
+ "#{ type }(#{ prefix }#{ name })"
116
+ end
117
+
118
+ def add_value value
119
+ given true
120
+ values << value
121
+ end
122
+
123
+ def value
124
+ values.first
125
+ end
126
+
127
+ def argument_none?
128
+ argument.nil?
129
+ end
130
+
131
+ def argument_required?
132
+ argument and
133
+ argument.to_s.downcase.to_sym == :required
134
+ end
135
+ def argument_optional?
136
+ argument and
137
+ argument.to_s.downcase.to_sym == :optional
138
+ end
139
+
140
+ def optional?
141
+ not required?
142
+ end
143
+ def optional= bool
144
+ self.required !bool
145
+ end
146
+
147
+ =begin
148
+ def setup!
149
+ return false unless given?
150
+ adding_handlers do
151
+ check_arity
152
+ apply_casting
153
+ check_validation
154
+ end
155
+ true
156
+ end
157
+ =end
158
+
159
+ def setup!
160
+ adding_handlers do
161
+ check_arity
162
+ apply_casting
163
+ check_validation
164
+ end
165
+ end
166
+
167
+ def check_arity
168
+ return true if not given? and optional?
169
+
170
+ ex = values.size == 0 ? NotGiven : Arity
171
+
172
+ (raise ex, "#{ typename })" if values.size.zero? and argument_required?) unless arity == -1
173
+
174
+ if arity >= 0
175
+ min = arity
176
+ sign = ''
177
+ else
178
+ min = arity.abs - 1
179
+ sign = '-'
180
+ end
181
+
182
+ arity = min
183
+
184
+ =begin
185
+ puts
186
+ p :values => values
187
+ p :arity => arity
188
+ p :argument_required => argument_required?
189
+ p :argument_none => argument_none?
190
+ puts
191
+ =end
192
+ if values.size < arity
193
+ if argument_optional?
194
+ raise ex, "#{ typename }) #{ values.size }/#{ sign }#{ arity }" if(values.size < arity and values.size > 0)
195
+ elsif argument_required? or argument_none?
196
+ raise ex, "#{ typename }) #{ values.size }/#{ sign }#{ arity }" if(values.size < arity)
197
+ end
198
+ end
199
+ end
200
+
201
+ def apply_casting
202
+ if cast?
203
+ op = cast.respond_to?('call') ? cast : Cast[cast]
204
+ values.map! do |val|
205
+ Parameter.wrap_errors{ op.call val }
206
+ end
207
+ end
208
+ end
209
+
210
+ def check_validation
211
+ if validate?
212
+ values.each do |value|
213
+ validate[value] or
214
+ raise InValid, "invalid: #{ typename }=#{ value.inspect }"
215
+ end
216
+ end
217
+ end
218
+
219
+ def add_handlers e
220
+ esc =
221
+ class << e
222
+ self
223
+ end
224
+
225
+ this = self
226
+
227
+ %w[ before instead after ].each do |which|
228
+ getter = "error_handler_#{ which }"
229
+ query = "error_handler_#{ which }?"
230
+ if send(query)
231
+ handler = send getter
232
+ esc.module_eval do
233
+ define_method(getter) do |main|
234
+ main.instance_eval_block self, &handler
235
+ end
236
+ end
237
+ end
238
+ end
239
+ end
240
+
241
+ def adding_handlers
242
+ begin
243
+ yield
244
+ rescue Exception => e
245
+ add_handlers e
246
+ raise
247
+ end
248
+ end
249
+
250
+ class Argument < Parameter
251
+ fattr 'required' => true
252
+
253
+ fattr 'synopsis' do
254
+ label = name
255
+ op = required ? "->" : "~>"
256
+ value = defaults.size > 0 ? "#{ name }=#{ defaults.join ',' }" : name
257
+ value = "#{ cast }(#{ value })" if(cast and not cast.respond_to?(:call))
258
+ "#{ label } (#{ arity } #{ op } #{ value })"
259
+ end
260
+ end
261
+
262
+ class Option < Parameter
263
+ fattr 'required' => false
264
+ fattr 'arity' => 0
265
+
266
+ fattr 'synopsis' do
267
+ long, *short = names
268
+ value = cast || name
269
+ rhs = argument ? (argument == :required ? "=#{ name }" : "=[#{ name }]") : nil
270
+ label = ["--#{ long }#{ rhs }", short.map{|s| "-#{ s }"}].flatten.join(", ")
271
+ unless argument_none?
272
+ op = required ? "->" : "~>"
273
+ value = defaults.size > 0 ? "#{ name }=#{ defaults.join ',' }" : name
274
+ value = "#{ cast }(#{ value })" if(cast and not cast.respond_to?(:call))
275
+ "#{ label } (#{ arity } #{ op } #{ value })"
276
+ else
277
+ label
278
+ end
279
+ end
280
+ end
281
+
282
+ class Keyword < Parameter
283
+ fattr 'required' => false
284
+ fattr 'argument' => :required
285
+
286
+ fattr 'synopsis' do
287
+ label = "#{ name }=#{ name }"
288
+ op = required ? "->" : "~>"
289
+ value = defaults.size > 0 ? "#{ name }=#{ defaults.join ',' }" : name
290
+ value = "#{ cast }(#{ value })" if(cast and not cast.respond_to?(:call))
291
+ "#{ label } (#{ arity } #{ op } #{ value })"
292
+ end
293
+ end
294
+
295
+ class Environment < Parameter
296
+ fattr 'argument' => :required
297
+
298
+ fattr 'synopsis' do
299
+ label = "env[#{ name }]=#{ name }"
300
+ op = required ? "->" : "~>"
301
+ value = defaults.size > 0 ? "#{ name }=#{ defaults.join ',' }" : name
302
+ value = "#{ cast }(#{ value })" if(cast and not cast.respond_to?(:call))
303
+ "#{ label } (#{ arity } #{ op } #{ value })"
304
+ end
305
+ end
306
+
307
+ class List < ::Array
308
+ def parse argv, env
309
+ ignore, stop = [], argv.index('--')
310
+ if stop
311
+ ignore = argv[stop .. -1]
312
+ (argv.size - stop).times{ argv.pop }
313
+ end
314
+ parse_options argv
315
+ return 'help' if detect{|p| p.name.to_s == 'help' and p.given?}
316
+ parse_keywords argv
317
+ parse_arguments argv
318
+ parse_environment env
319
+ defaults!
320
+ validate!
321
+ argv.push *ignore[1 .. -1] unless ignore.empty?
322
+ self
323
+ end
324
+
325
+ def parse_options argv, params = nil
326
+ params ||= options
327
+
328
+ spec, h, s = [], {}, {}
329
+
330
+ params.each do |p|
331
+ head, *tail = p.names
332
+ long = "--#{ head }"
333
+ shorts = tail.map{|t| "-#{ t }"}
334
+ type =
335
+ if p.argument_required? then GetoptLong::REQUIRED_ARGUMENT
336
+ elsif p.argument_optional? then GetoptLong::OPTIONAL_ARGUMENT
337
+ else GetoptLong::NO_ARGUMENT
338
+ end
339
+ a = [ long, shorts, type ].flatten
340
+ spec << a
341
+ h[long] = p
342
+ s[long] = a
343
+ end
344
+
345
+ begin
346
+ GetoptLong.new(argv, *spec).each do |long, value|
347
+ value =
348
+ case s[long].last
349
+ when GetoptLong::NO_ARGUMENT
350
+ value.empty? ? true : value
351
+ when GetoptLong::OPTIONAL_ARGUMENT
352
+ value.empty? ? true : value
353
+ when GetoptLong::REQUIRED_ARGUMENT
354
+ value
355
+ end
356
+ p = h[long]
357
+ p.add_value value
358
+ end
359
+ rescue GetoptLong::AmbigousOption, GetoptLong::NeedlessArgument,
360
+ GetoptLong::MissingArgument, GetoptLong::InvalidOption => e
361
+ c = Parameter.const_get e.class.name.split(/::/).last
362
+ ex = c.new e.message
363
+ ex.set_backtrace e.message
364
+ ex.extend Softspoken
365
+ raise ex
366
+ end
367
+
368
+ =begin
369
+ params.each do |p|
370
+ p.setup!
371
+ end
372
+ =end
373
+ end
374
+
375
+ def parse_arguments argv, params=nil
376
+ params ||= select{|p| p.type == :argument}
377
+
378
+ params.each do |p|
379
+ if p.arity >= 0
380
+ p.arity.times do
381
+ break if argv.empty?
382
+ value = argv.shift
383
+ p.add_value value
384
+ end
385
+ else
386
+ arity = p.arity.abs - 1
387
+ arity.times do
388
+ break if argv.empty?
389
+ value = argv.shift
390
+ p.add_value value
391
+ end
392
+ argv.size.times do
393
+ value = argv.shift
394
+ p.add_value value
395
+ end
396
+ end
397
+ end
398
+
399
+ =begin
400
+ params.each do |p|
401
+ p.setup!
402
+ end
403
+ =end
404
+ end
405
+
406
+ def parse_keywords argv, params=nil
407
+ params ||= select{|p| p.type == :keyword}
408
+
409
+ replacements = {}
410
+
411
+ params.each do |p|
412
+ names = p.names
413
+ name = names.sort_by{|n| [n.size,n]}.last
414
+
415
+ kre = %r/^\s*(#{ names.join '|' })\s*=/
416
+ opt = "--#{ name }"
417
+ i = -1
418
+
419
+ argv.each_with_index do |a, idx|
420
+ i += 1
421
+ b = argv[idx + 1]
422
+ s = "#{ a }#{ b }"
423
+ m, key, *ignored = kre.match(s).to_a
424
+ if m
425
+ replacements[i] ||= a.gsub %r/^\s*#{ key }/, opt
426
+ next
427
+ end
428
+ =begin
429
+ abbrev = name.index(key) == 0
430
+ if abbrev
431
+ replacements[i] ||= a.gsub %r/^\s*#{ key }/, opt
432
+ end
433
+ =end
434
+ end
435
+ end
436
+
437
+ replacements.each do |i, r|
438
+ argv[i] = r
439
+ end
440
+
441
+ parse_options argv, params
442
+ end
443
+
444
+ def parse_environment env, params=nil
445
+ params ||= select{|p| p.type == :environment}
446
+
447
+ params.each do |p|
448
+ names = p.names
449
+ name = names.first
450
+ value = env[name]
451
+ next unless value
452
+ p.add_value value
453
+ end
454
+
455
+ =begin
456
+ params.each do |p|
457
+ p.setup!
458
+ end
459
+ =end
460
+ end
461
+
462
+ def defaults!
463
+ each do |p|
464
+ if(p.defaults? and (not p.given?))
465
+ p.defaults.each do |default|
466
+ p.values << default # so as NOT to set 'given?'
467
+ end
468
+ end
469
+ end
470
+ end
471
+
472
+ def validate!
473
+ each do |p|
474
+ #p.adding_handlers do
475
+ #next if p.arity == -1
476
+ #raise NotGiven, "#{ p.typename } not given" if(p.required? and (not p.given?))
477
+ #end
478
+ p.setup!
479
+ end
480
+ end
481
+
482
+ [:parameter, :option, :argument, :keyword, :environment].each do |m|
483
+ define_method("#{ m }s"){ select{|p| p.type == m or m == :parameter} }
484
+
485
+ define_method("has_#{ m }?") do |name, *names|
486
+ catch :has do
487
+ names = Cast.list_of_string name, *names
488
+ send("#{ m }s").each do |param|
489
+ common = Cast.list_of_string(param.names) & names
490
+ throw :has, true unless common.empty?
491
+ end
492
+ false
493
+ end
494
+ end
495
+ end
496
+
497
+ def delete name, *names
498
+ name, *names = name.names if Parameter === name
499
+ names = Cast.list_of_string name, *names
500
+ keep = []
501
+ each do |param|
502
+ common = Cast.list_of_string(param.names) & names
503
+ keep << param if common.empty?
504
+ end
505
+ replace keep
506
+ end
507
+
508
+ def << *a
509
+ delete *a
510
+ super
511
+ end
512
+ end
513
+
514
+ class DSL
515
+ def self.evaluate param, &block
516
+ new(param).evaluate(&block)
517
+ end
518
+
519
+ attr 'param'
520
+ alias_method 'evaluate', 'instance_eval'
521
+
522
+ def initialize param
523
+ @param = param
524
+ end
525
+
526
+ def fattr a = nil, &block
527
+ name = param.name
528
+ a ||= name
529
+ b = fattr_block_for name, &block
530
+ Main.current.module_eval{ fattr *a, &b }
531
+ end
532
+ alias_method 'attribute', 'fattr'
533
+
534
+ def fattr_block_for name, &block
535
+ block ||= lambda{|param| [0,1].include?(param.arity) ? param.value : param.values }
536
+ lambda{ block.call self.param[name] }
537
+ end
538
+
539
+ def attr *a, &b
540
+ fattr *a, &b
541
+ end
542
+
543
+ def example *list
544
+ list.flatten.compact.each do |elem|
545
+ param.examples << elem.to_s
546
+ end
547
+ end
548
+ alias_method "examples", "example"
549
+
550
+
551
+ def type *sym
552
+ sym.size == 0 ? param.type : (param.type = sym.first)
553
+ end
554
+ def type?
555
+ param.type?
556
+ end
557
+
558
+ def synopsis *arg
559
+ arg.size == 0 ? param.synopsis : (param.synopsis arg.first)
560
+ end
561
+
562
+ def argument arg
563
+ param.argument arg
564
+ end
565
+ def argument_required bool = true
566
+ if bool
567
+ param.argument :required
568
+ else
569
+ param.argument false
570
+ end
571
+ end
572
+ def argument_required?
573
+ param.argument_required?
574
+ end
575
+
576
+ def argument_optional bool = true
577
+ if bool
578
+ param.argument :optional
579
+ else
580
+ param.argument false
581
+ end
582
+ end
583
+ def argument_optional?
584
+ param.argument_optional?
585
+ end
586
+
587
+ def required bool = true
588
+ param.required = bool
589
+ end
590
+ def required?
591
+ param.required?
592
+ end
593
+
594
+ def optional bool = true
595
+ if bool
596
+ param.required !bool
597
+ else
598
+ param.required bool
599
+ end
600
+ end
601
+ def optional?
602
+ param.optional?
603
+ end
604
+
605
+ def cast sym=nil, &b
606
+ param.cast = sym || b
607
+ end
608
+ def cast?
609
+ param.cast?
610
+ end
611
+
612
+ def validate sym=nil, &b
613
+ param.validate = sym || b
614
+ end
615
+ def validate?
616
+ param.validate?
617
+ end
618
+
619
+ def description s
620
+ param.description = s.to_s
621
+ end
622
+ def description?
623
+ param.description?
624
+ end
625
+ alias_method 'desc', 'description'
626
+
627
+ def default value, *values
628
+ param.defaults.push value
629
+ param.defaults.push *values
630
+ param.defaults
631
+ end
632
+ def defaults?
633
+ param.defaults?
634
+ end
635
+ def defaults value, *values
636
+ param.defaults.push value
637
+ param.defaults.push *values
638
+ param.defaults
639
+ end
640
+ def defaults?
641
+ param.defaults?
642
+ end
643
+
644
+ def arity value
645
+ raise Arity if value.nil?
646
+ value = -1 if value.to_s == '*'
647
+ value = Integer value
648
+ raise Arity if value.zero?
649
+ param.arity = value
650
+ if param.arity == -1
651
+ optional true
652
+ end
653
+ value
654
+ end
655
+ def arity?
656
+ param.arity?
657
+ end
658
+
659
+ def error which = :instead, &block
660
+ param.send "error_handler_#{ which }=", block
661
+ end
662
+ end
663
+
664
+ class Table < ::Array
665
+ def initialize
666
+ super()
667
+ self.fields = []
668
+ extend BoundsCheck
669
+ end
670
+
671
+ def to_options
672
+ (hash = self.to_hash ).keys.each { |key| hash[key] = hash[key].value }
673
+ return hash
674
+ end
675
+
676
+ module BoundsCheck
677
+ def [] *a, &b
678
+ p = super
679
+ ensure
680
+ raise NoneSuch, a.join(',') unless p
681
+ end
682
+ end
683
+ end
684
+ end
685
+ end