rubyment 0.6.25540755 → 0.6.25563758

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.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/lib/rubyment.rb +1586 -139
  3. metadata +1 -1
data/lib/rubyment.rb CHANGED
@@ -1,6 +1,14 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
 
4
+ =begin
5
+ # begin_documentation
6
+ TrueClass will be changed just by including
7
+ this file or requiring rubyment, which is not the
8
+ best approach, but kept to respect the open/closed
9
+ principle, but new functions should be added here.
10
+ # end_documentation
11
+ =end
4
12
  class TrueClass
5
13
  # returns +false+ (purpose of simplifying
6
14
  # functional programming)
@@ -10,6 +18,20 @@ class TrueClass
10
18
  end
11
19
 
12
20
 
21
+ =begin
22
+ # begin_documentation
23
+ Object will be changed just by including
24
+ this file or requiring rubyment, which is not the
25
+ best approach, but kept to respect the open/closed
26
+ principle, but new functions should be added here.
27
+
28
+ only a bunch of methods, is, however, added:
29
+ . negate_me
30
+ . to_nil
31
+ . nne
32
+
33
+ # end_documentation
34
+ =end
13
35
  class Object
14
36
  # returns +self+ if +self+ is not considered
15
37
  # to be the neutral element of its class.
@@ -44,53 +66,804 @@ class Object
44
66
  end
45
67
 
46
68
 
47
- # returns nil out of an object.
48
- # usage examples:
49
- # "this_parameter_is_nil".to_nil
50
- def to_nil
51
- nil
52
- end
69
+ # returns nil out of an object.
70
+ # usage examples:
71
+ # "this_parameter_is_nil".to_nil
72
+ def to_nil
73
+ nil
74
+ end
75
+
76
+
77
+ # returns +!self+, unless +unless_condition+
78
+ # is +true+; in such case returns +self+.
79
+ # e.g: +false.negate_me true+ returns
80
+ # +false+.
81
+ # (by default, if no params are given,
82
+ # just # negates +self+)
83
+ # experiment
84
+ # [1, 2, nil, 3, nil, 4].select &:negate_me
85
+ # to find the nil elements in an array
86
+ def negate_me condition=true
87
+ (condition) && (
88
+ !self
89
+ ) || (!condition) && (
90
+ self
91
+ )
92
+ end
93
+ end
94
+
95
+
96
+ =begin
97
+ # begin_documentation
98
+ This module receives functions that are being worked on.
99
+ # end_documentation
100
+ =end
101
+ module RubymentExperimentModule
102
+
103
+
104
+ =begin
105
+ alias for #bled
106
+ =end
107
+ def experiment__bled args=[], &block
108
+ bled args, &block
109
+ end
110
+
111
+
112
+ =begin
113
+
114
+ # documentation_begin
115
+ # short_desc = "tests the function #call_or_itself"
116
+ @memory[:documentation].push = {
117
+ :function => :call_or_itself,
118
+ :short_desc => short_desc,
119
+ :description => "calls the method #call of an object, or return the object itself",
120
+ :params => [
121
+ {
122
+ :name => :args,
123
+ :description => "list of parameters",
124
+ :duck_type => Array,
125
+ :default_behavior => [],
126
+ :params => [
127
+ {
128
+ :name => :object,
129
+ :duck_type => Object,
130
+ :default_behavior => :nil,
131
+ :description => "object to be called, if responds to #call, or to return itself",
132
+ },
133
+ {
134
+ :name => :return_dont_call,
135
+ :duck_type => Object,
136
+ :default_behavior => :nil,
137
+ :description => "forces an object to return itself even when it reponds to #call",
138
+ },
139
+ {
140
+ :name => :debug,
141
+ :duck_type => Object,
142
+ :default_behavior => :nil,
143
+ :description => "prints debug information to the __IO__ specified by __@memory[:stderr]__ (STDERR by default)",
144
+ },
145
+ {
146
+ :name => :reserved,
147
+ :duck_type => Object,
148
+ :default_behavior => :nil,
149
+ :description => "for future use",
150
+ },
151
+ ],
152
+ },
153
+ ],
154
+ :return_value => [
155
+ {
156
+ :name => :args,
157
+ :description => "list of parameters",
158
+ :duck_type => Array,
159
+ :default_behavior => [],
160
+ :params => [
161
+ {
162
+ :name => :reserved,
163
+ :duck_type => Object,
164
+ :default_behavior => :nil,
165
+ :description => "for future use",
166
+ },
167
+ ],
168
+ },
169
+ ],
170
+ }
171
+ # documentation_end
172
+
173
+ =end
174
+ def call_or_itself args=[]
175
+ stderr = @memory[:stderr]
176
+ object,
177
+ return_dont_call,
178
+ debug,
179
+ reserved = args
180
+ debug = debug.nne
181
+ debug && (stderr.puts "{#{__method__} starting")
182
+ debug && (stderr.puts "args=#{args.inspect}")
183
+ will_call = (object.respond_to? :call) && return_dont_call.negate_me
184
+ debug && (stderr.puts "will_call=#{will_call.inspect}")
185
+ will_call && (rv = object.call)
186
+ debug && (stderr.puts "provisory return value: #{rv.inspect}")
187
+ will_call.negate_me && (rv = object)
188
+ debug && (stderr.puts "will return #{rv.inspect}")
189
+ debug && (stderr.puts "#{__method__} returning}")
190
+ rv
191
+ end
192
+
193
+
194
+ =begin
195
+ # documentation_begin
196
+ # short_desc = "tests the function #experiment__whether"
197
+ @memory[:documentation].push = {
198
+ :function => :experiment__whether,
199
+ :short_desc => short_desc,
200
+ :description => "",
201
+ :params => [
202
+ {
203
+ :name => :args,
204
+ :description => "list of parameters",
205
+ :duck_type => Array,
206
+ :default_behavior => [],
207
+ :params => [
208
+ {
209
+ :name => :condition,
210
+ :duck_type => :boolean,
211
+ :default_behavior => :nil,
212
+ :description => "any condition, used to decided which parameter will be run",
213
+ },
214
+ {
215
+ :name => :run_if_true,
216
+ :duck_type => Proc,
217
+ :default_behavior => :nil,
218
+ :description => "block will be called if condition is true",
219
+ },
220
+ {
221
+ :name => :run_if_false,
222
+ :duck_type => Proc,
223
+ :default_behavior => :nil,
224
+ :description => "block will be called if condition is true",
225
+ },
226
+ {
227
+ :name => :return_dont_run,
228
+ :duck_type => Array,
229
+ :default_behavior => [],
230
+ :description => "forces blocks from being called. first element prevents the return_if_true block to be called (so the object return_if_true is returned). the second applies to run_if_false",
231
+ },
232
+ {
233
+ :name => :debug,
234
+ :duck_type => Object,
235
+ :default_behavior => :nil,
236
+ :description => "prints debug information to the __IO__ specified by __@memory[:stderr]__ (STDERR by default)",
237
+ },
238
+ {
239
+ :name => :reserved,
240
+ :duck_type => Object,
241
+ :default_behavior => :nil,
242
+ :description => "for future use",
243
+ },
244
+ ],
245
+ },
246
+ ],
247
+ :return_value => [
248
+ {
249
+ :name => :rv,
250
+ :description => "value returned by the block run",
251
+ :duck_type => Object,
252
+ :default_behavior => :nil,
253
+ },
254
+ ],
255
+ }
256
+ # documentation_end
257
+ =end
258
+
259
+ def experiment__whether args=[]
260
+ stderr = @memory[:stderr]
261
+ condition,
262
+ run_if_true,
263
+ run_if_false,
264
+ return_dont_run,
265
+ debug,
266
+ reserved = args
267
+ debug = debug.nne
268
+ debug && (stderr.puts "{#{__method__} starting")
269
+ debug && (stderr.puts "args=#{args.inspect}")
270
+ return_don_run_true = (containerize return_dont_run)[0]
271
+ return_don_run_false = (containerize return_dont_run)[1]
272
+ debug && (stderr.puts "[return_don_run_true, return_don_run_false]=#{[return_don_run_true, return_don_run_false].inspect}")
273
+ condition && (rv = call_or_itself [run_if_true, return_don_run_true])
274
+ debug && (stderr.puts "provisory return value: #{rv.inspect}")
275
+ condition.negate_me && (rv = call_or_itself [run_if_false, return_don_run_false])
276
+ debug && (stderr.puts "will return #{rv.inspect}")
277
+ debug && (stderr.puts "#{__method__} returning}")
278
+ rv
279
+ end
280
+
281
+
282
+ =begin
283
+ # documentation_begin
284
+ # short_desc = "tests the function #experiment__tester"
285
+ @memory[:documentation].push = {
286
+ :function => :experiment__tester,
287
+ :short_desc => short_desc,
288
+ :description => "",
289
+ :params => [
290
+ {
291
+ :name => :args,
292
+ :description => "list of parameters",
293
+ :duck_type => Array,
294
+ :default_behavior => [],
295
+ :params => [
296
+ {
297
+ :name => :test_cases,
298
+ :duck_type => Array,
299
+ :default_behavior => :[],
300
+ :description => "Array having the fields: __test_id__, __test_expected_value__ and __actual_params__. __actual_params__ is an __Array__ having as first member __method_name__ to be called, and all its remaining args __method_args__ (a __splat__) will be given to __method_name__",
301
+ },
302
+ {
303
+ :name => :debug,
304
+ :duck_type => Object,
305
+ :default_behavior => :nil,
306
+ :description => "prints debug information to the __IO__ specified by __@memory[:stderr]__ (STDERR by default)",
307
+ },
308
+ {
309
+ :name => :reserved,
310
+ :duck_type => Object,
311
+ :default_behavior => :nil,
312
+ :description => "for future use",
313
+ },
314
+ ],
315
+ },
316
+ ],
317
+ :return_value => [
318
+ {
319
+ :name => :args,
320
+ :description => "__true__ if tests were successful, __false__ otherwise",
321
+ :duck_type => :boolean,
322
+ },
323
+ ],
324
+ }
325
+ # documentation_end
326
+ =end
327
+ def experiment__tester args=[]
328
+ stderr = @memory[:stderr]
329
+ test_cases,
330
+ debug,
331
+ reserved = args
332
+
333
+ debug = debug.nne
334
+ debug && (stderr.puts "{#{__method__} starting")
335
+ debug && (stderr.puts "caller=#{caller_label.inspect}")
336
+ debug && (stderr.puts backtrace)
337
+ debug && (stderr.puts "args=#{args.inspect}")
338
+ test_cases = test_cases.nne [
339
+ # [ :id, :expectation, :actual_params ],
340
+ # :actual_params: array with :method_name + :method_args
341
+ ]
342
+ expectation = {}
343
+ actual = {}
344
+ debug && (stderr.puts "test_cases.size=#{test_cases.size}")
345
+ test_cases.each_with_index{ |test_case|
346
+ debug && (stderr.puts "test_case=[test_case_id, test_expectation, actual_params]=#{test_case.inspect}")
347
+ test_case_id, test_expectation, actual_params = test_case
348
+ actual_params_method_name,
349
+ *actual_params_method_args = actual_params
350
+ debug && (stderr.puts "will send: #{actual_params_method_name.to_s}(*#{actual_params_method_args.inspect})")
351
+ result = send actual_params_method_name, *actual_params_method_args
352
+ expectation[test_case_id] = test_expectation
353
+ actual[test_case_id] = result
354
+ }
355
+ judgement = actual.keys.map {|test_case|
356
+ [expectation[test_case], actual[test_case] , test_case]
357
+ }.map(&method("expect_equal")).all?
358
+
359
+ rv = judgement
360
+ debug && (stderr.puts "will return #{rv.inspect}")
361
+ debug && (stderr.puts "#{__method__} returning}")
362
+ rv
363
+ end
364
+
365
+
366
+ =begin
367
+ =end
368
+ def experiment__send_array_base args=[]
369
+ sender,
370
+ object_to_send,
371
+ destination,
372
+ debug,
373
+ shallow,
374
+ args_to_bled,
375
+ send_to_self,
376
+ reserved = args
377
+
378
+ stderr = @memory[:stderr]
379
+ debug = debug.nne
380
+ debug = 1
381
+ debug && (stderr.puts "{#{__method__} starting")
382
+ debug && (stderr.puts "args=#{args.inspect}")
383
+ debug && (stderr.puts "debug=#{args[3].inspect}")
384
+
385
+ method_to_send,
386
+ *args_to_send = sender
387
+ debug && (stderr.puts "general case{: #{object_to_send.inspect}.#{method_to_send.inspect}(#{args_to_send.inspect}) }")
388
+
389
+ send_block = bled(args_to_bled) {
390
+ object_to_send.send method_to_send, *args_to_send
391
+ }.first
392
+
393
+ default_block = bled(args_to_bled) {
394
+ args_to_send
395
+ }.first
396
+
397
+ rv = experiment__whether [
398
+ method_to_send,
399
+ send_block,
400
+ default_block,
401
+ ]
402
+
403
+ debug && (stderr.puts "will return #{rv.inspect}")
404
+ debug && (stderr.puts "#{__method__} returning}")
405
+ rv
406
+ end
407
+
408
+
409
+ end
410
+
411
+
412
+ =begin
413
+ # begin_documentation
414
+ This module receives only functions that are maintained.
415
+ Ie, the non-deprecated or not under deprecation functions.
416
+ # end_documentation
417
+ =end
418
+ module RubymentMaintainedModule
419
+
420
+
421
+ =begin
422
+ # documentation_begin
423
+ # short_desc = "tests the function #exception_info_base"
424
+ @memory[:documentation].push = {
425
+ :function => :exception_info_base,
426
+ :short_desc => short_desc,
427
+ :description => "",
428
+ :params => [
429
+ {
430
+ :name => :args,
431
+ :description => "list of parameters",
432
+ :duck_type => Array,
433
+ :default_behavior => [],
434
+ :params => [
435
+ {
436
+ :name => :exception,
437
+ :duck_type => Exception,
438
+ :default_behavior => nil,
439
+ :description => "exception to extract info from",
440
+ },
441
+ {
442
+ :name => :max_str_index,
443
+ :duck_type => FixNum,
444
+ :default_behavior => -1,
445
+ :description => "limit the full string output to this last index",
446
+ },
447
+ {
448
+ :name => :reserved,
449
+ :duck_type => Object,
450
+ :default_behavior => nil,
451
+ :description => "reserved for future use",
452
+ },
453
+ ],
454
+ },
455
+ ],
456
+ :return_value => [
457
+ {
458
+ :name => :short,
459
+ :duck_type => String,
460
+ :default_behavior => "",
461
+ :description => "a brief about the exception; normally an exception message",
462
+ },
463
+ {
464
+ :name => :full,
465
+ :duck_type => String,
466
+ :default_behavior => "",
467
+ :description => "all the information about the exception; normally an exception message, backtrace, class and inspection",
468
+ },
469
+ {
470
+ :name => :inspection,
471
+ :duck_type => String,
472
+ :default_behavior => "",
473
+ :description => "the exception inspection",
474
+ },
475
+ {
476
+ :name => :backtrace,
477
+ :duck_type => Object,
478
+ :duck_type => [:_a, Array, :strings],
479
+ :description => the exception bactrace",
480
+ },
481
+ {
482
+ :name => :message,
483
+ :duck_type => String,
484
+ :default_behavior => "",
485
+ :description => "the exception message",
486
+ },
487
+ {
488
+ :name => :class_,
489
+ :duck_type => String,
490
+ :default_behavior => "",
491
+ :description => "the exception class",
492
+ },
493
+ {
494
+ :name => :reserved,
495
+ :duck_type => Object,
496
+ :default_behavior => nil,
497
+ :description => "reserved for future use",
498
+ },
499
+ ],
500
+ }
501
+ # documentation_end
502
+ =end
503
+ def exception_info_base args=[]
504
+ exception,
505
+ max_str_index,
506
+ reserved = args
507
+ inspection = exception.inspect
508
+ backtrace = exception.backtrace
509
+ class_ = exception.class
510
+ message = exception.message,
511
+ short = message
512
+ full = (
513
+ [
514
+ "message{",
515
+ message,
516
+ "}",
517
+ "backtrace{",
518
+ ] +
519
+ backtrace.to_a +
520
+ [
521
+ "}",
522
+ "class{",
523
+ class_,
524
+ "}",
525
+ "}",
526
+ "inspection{",
527
+ inspection,
528
+ "}",
529
+ ]
530
+ ).join "\n"
531
+
532
+ full = string_truncate [
533
+ full,
534
+ max_str_index,
535
+ ]
536
+ [short, full, inspection, backtrace, message, class_]
537
+ end
538
+
539
+
540
+ =begin
541
+ # documentation_begin
542
+ # short_desc = "tests the function #bled"
543
+ @memory[:documentation].push = {
544
+ :function => :bled,
545
+ :short_desc => short_desc,
546
+ :description => "",
547
+ :params => [
548
+ {
549
+ :name => :args,
550
+ :description => "list of parameters (splat)",
551
+ :duck_type => splat,
552
+ :default_behavior => [],
553
+ :params => [
554
+ {
555
+ :name => :default_on_exception,
556
+ :duck_type => Object,
557
+ :default_behavior => :nil,
558
+ :description => "if an exception happens, this value will be returned in the first element of the return value",
559
+ },
560
+ {
561
+ :name => :dont_rescue,
562
+ :duck_type => Object,
563
+ :default_behavior => :nil,
564
+ :description => "do not rescue exceptions",
565
+ },
566
+ {
567
+ :name => :output_backtrace,
568
+ :duck_type => Object,
569
+ :default_behavior => :nil,
570
+ :description => "output when an exception happens",
571
+ },
572
+ {
573
+ :name => :backtrace_max_str_len,
574
+ :duck_type => FixNum,
575
+ :default_behavior => :nil,
576
+ :description => "backtrace outputs can be long, use this to limit it",
577
+ },
578
+ {
579
+ :name => :debug,
580
+ :duck_type => Object,
581
+ :default_behavior => :nil,
582
+ :description => "prints debug information to the __IO__ specified by __@memory[:stderr]__ (STDERR by default)",
583
+ },
584
+ {
585
+ :name => :reserved,
586
+ :duck_type => Object,
587
+ :default_behavior => :nil,
588
+ :description => "for future use",
589
+ },
590
+ ],
591
+ },
592
+ ],
593
+ :return_value => [
594
+ {
595
+ :name => :args,
596
+ :description => "list of parameters",
597
+ :duck_type => Array,
598
+ :default_behavior => [],
599
+ :params => [
600
+ {
601
+ :name => :actual_block_return,
602
+ :duck_type => Object,
603
+ :default_behavior => :nil,
604
+ :description => "the actual return value of the block call",
605
+ },
606
+ {
607
+ :name => :exception_info,
608
+ :duck_type => Array,
609
+ :default_behavior => [],
610
+ :description => "exception info if an exception happened, as returned by :exception_information_base",
611
+ },
612
+ {
613
+ :name => :exception,
614
+ :duck_type => Exception,
615
+ :default_behavior => :nil,
616
+ :description => "the exception that happened, if any",
617
+ },
618
+ {
619
+ :name => :reserved,
620
+ :duck_type => Object,
621
+ :default_behavior => :nil,
622
+ :description => "for future use",
623
+ },
624
+ ],
625
+ },
626
+ ],
627
+ }
628
+ # documentation_end
629
+ =end
630
+ def bled args=[], &block
631
+ stderr = @memory[:stderr]
632
+ default_on_exception,
633
+ dont_rescue,
634
+ output_backtrace,
635
+ backtrace_max_str_len,
636
+ debug,
637
+ reserved = args
638
+ debug = debug.nne
639
+ debug && (stderr.puts "{#{__method__} starting")
640
+ debug && (stderr.puts "args=#{args.inspect}")
641
+ block ||= lambda {|*block_args|}
642
+ rv = Proc.new { |*block_args|
643
+ (debug || output_backtrace) && (stderr.puts "{#{__method__} block starting")
644
+ (debug || output_backtrace) && (stderr.puts "block_args=#{block_args.inspect}")
645
+ brv = begin
646
+ [ (block.call *block_args), nil, nil]
647
+ rescue => e
648
+ e_info = exception_info_base [
649
+ e,
650
+ backtrace_max_str_len
651
+ ]
652
+ (debug || output_backtrace) && (stderr.puts "#{__method__} block: #{block.inspect}\nfull exception info:\n#{e_info[1]}")
653
+ (debug || output_backtrace) && (stderr.puts "#{__method__} block: dont_rescue=#{dont_rescue}; true means will rethrow")
654
+ dont_rescue && (raise e)
655
+ [ default_on_exception, e_info, e ]
656
+ end
657
+ (debug || output_backtrace) && (stderr.puts "block #{block.inspect} will return #{brv.inspect}")
658
+ (debug || output_backtrace) && (stderr.puts "#{__method__} block returning}")
659
+ brv
660
+ }
661
+ rv = [ rv ]
662
+ debug && (stderr.puts "will return #{rv.inspect}")
663
+ debug && (stderr.puts "#{__method__} returning}")
664
+ rv
665
+ end
666
+
667
+
668
+ =begin
669
+ # documentation_begin
670
+ # short_desc = "tests the function #string_truncate"
671
+ @memory[:documentation].push = {
672
+ :function => :string_truncate,
673
+ :short_desc => short_desc,
674
+ :description => "",
675
+ :params => [
676
+ {
677
+ :name => :args,
678
+ :description => "list of parameters",
679
+ :duck_type => Array,
680
+ :default_behavior => [],
681
+ :params => [
682
+ {
683
+ :name => :max_str_index,
684
+ :duck_type => FixNum,
685
+ :default_behavior => -1,
686
+ :description => "index (not size) where to truncate the string (this is the index of the last char)",
687
+ },
688
+ {
689
+ :name => :reticenses,
690
+ :duck_type => String,
691
+ :default_behavior => "...",
692
+ :description => "string to attach to the result when the resulting string is smaller than the original one (ie, has actually been truncated)",
693
+ },
694
+ ],
695
+ },
696
+ ],
697
+ :return_value =>
698
+ {
699
+ :name => :truncated_string,
700
+ :description => "truncated string",
701
+ :duck_type => String,
702
+ :default_behavior => :str,
703
+ },
704
+
705
+ }
706
+ # documentation_end
707
+ =end
708
+ def string_truncate args=[]
709
+ str,
710
+ max_str_index,
711
+ reticenses,
712
+ reserved = args
713
+ output_max_str_index = @memory[:output_max_str_index]
714
+ output_max_str_index = output_max_str_index.nne -1
715
+ max_str_index = max_str_index.nne output_max_str_index
716
+ max_str_index = max_str_index.to_i
717
+ reticenses = reticenses.nne "..."
718
+ sliced_str = str.slice(0..max_str_index)
719
+ reticenses = (sliced_str.size < str.size ) && reticenses || ""
720
+ "#{sliced_str}#{reticenses}"
721
+ end
722
+
723
+
53
724
 
725
+ end
54
726
 
55
- # returns +!self+, unless +unless_condition+
56
- # is +true+; in such case returns +self+.
57
- # e.g: +false.negate_me true+ returns
58
- # +false+.
59
- # (by default, if no params are given,
60
- # just # negates +self+)
61
- def negate_me condition=true
62
- # STDERR.puts "negate_me"
63
- (condition) && (
64
- # STDERR.puts "condition"
65
- # STDERR.puts "#{self.inspect}"
66
- !self
67
- ) || (!condition) && (
68
- # STDERR.puts "!condition"
69
- self
70
- )
727
+
728
+ =begin
729
+ # begin_documentation
730
+ This module receives only functions that are deprecated.
731
+ They are still kept in Rubyment, but they won't receive
732
+ more updates, because there is a different more modern
733
+ way of achieving the same results.
734
+ The functions here are also not used by any function in
735
+ #RubymentMaintainedModule.
736
+ # end_documentation
737
+ =end
738
+ module RubymentDeprecatedModule
739
+
740
+
741
+ =begin
742
+ # documentation_begin
743
+ # short_desc = "tests the function #exception_information_base"
744
+ @memory[:documentation].push = {
745
+ :function => :exception_information_base,
746
+ :short_desc => short_desc,
747
+ :description => "",
748
+ :params => [
749
+ {
750
+ :name => :args,
751
+ :description => "list of parameters",
752
+ :duck_type => Array,
753
+ :default_behavior => [],
754
+ :params => [
755
+ {
756
+ :name => :exception,
757
+ :duck_type => Exception,
758
+ :default_behavior => nil,
759
+ :description => "exception to extract info from",
760
+ },
761
+ {
762
+ :name => :max_str_index,
763
+ :duck_type => FixNum,
764
+ :default_behavior => -1,
765
+ :description => "limit the full string output to this last index",
766
+ },
767
+ {
768
+ :name => :reserved,
769
+ :duck_type => Object,
770
+ :default_behavior => nil,
771
+ :description => "reserved for future use",
772
+ },
773
+ ],
774
+ },
775
+ ],
776
+ :return_value => [
777
+ {
778
+ :name => :short,
779
+ :duck_type => String,
780
+ :default_behavior => "",
781
+ :description => "a brief about the exception; normally an exception inspection",
782
+ },
783
+ {
784
+ :name => :full,
785
+ :duck_type => String,
786
+ :default_behavior => "",
787
+ :description => "all the information about the exception; normally an exception inspection and bactrace",
788
+ },
789
+ {
790
+ :name => :inspection,
791
+ :duck_type => String,
792
+ :default_behavior => "",
793
+ :description => "the exception inspection",
794
+ },
795
+ {
796
+ :name => :backtrace,
797
+ :duck_type => Object,
798
+ :duck_type => [:_a, Array, :strings],
799
+ :description => the exception bactrace",
800
+ },
801
+ {
802
+ :name => :reserved,
803
+ :duck_type => Object,
804
+ :default_behavior => nil,
805
+ :description => "reserved for future use",
806
+ },
807
+ ],
808
+ }
809
+ # documentation_end
810
+ =end
811
+ def exception_information_base args=[]
812
+ exception,
813
+ max_str_index,
814
+ reserved = args
815
+ inspection = exception.inspect
816
+ backtrace = exception.backtrace
817
+ short = inspection
818
+ full = (
819
+ [
820
+ "inspection (message):",
821
+ inspect,
822
+ "",
823
+ "backtrace:",
824
+ "",
825
+ ] +
826
+ backtrace.to_a
827
+ ).join "\n"
828
+
829
+ full = string_truncate [
830
+ full,
831
+ max_str_index,
832
+ ]
833
+ [short, full, inspection, backtrace]
71
834
  end
835
+
836
+
72
837
  end
73
838
 
74
839
 
75
- # Collection of Ruby functions
76
- # * output
77
- # normally outputs to STDERR, with
78
- # no mercy
79
- # STDOUT, just qualified output:
80
- # only if the function is expected
81
- # to output something
82
- module RubymentModule
840
+ =begin
841
+ # begin_documentation
842
+ Group of functions under deprecation
83
843
 
84
- # this class very often needs to split
85
- # first argument and remaining elements.
86
- # args:
87
- # args
88
- # default:
89
- # ARGV
90
- # returns:
91
- # [ args[0], args[1..-1] ]
92
- def array_first_remainder args=ARGV
93
- [ args[0], args[1..-1] ]
844
+ to be included by #RubymentUnderDeprecationModule
845
+ # end_documentation
846
+ =end
847
+ module RubymentUnderDeprecationRuneFunctionsModule
848
+
849
+
850
+ # generic function for test__ functions
851
+ def test__tester args=[]
852
+ expectation = {}
853
+ actual = {}
854
+ test_cases = args
855
+ test_cases ||= [
856
+ # [ :id, :expectation, :actual_params ],
857
+ ]
858
+ test_cases.each_with_index{ |test_case|
859
+ test_case_id, test_expectation, actual_params = test_case
860
+ result = send actual_params[0], actual_params[1]
861
+ expectation[test_case_id] = test_expectation
862
+ actual[test_case_id] = result
863
+ }
864
+ judgement = actual.keys.map {|test_case|
865
+ [expectation[test_case], actual[test_case] , test_case]
866
+ }.map(&method("expect_equal")).all?
94
867
  end
95
868
 
96
869
 
@@ -250,6 +1023,9 @@ module RubymentModule
250
1023
  # another desirable case is to output
251
1024
  # the exception, but don't return it;
252
1025
  # not yet possible.
1026
+ # a third desirable case would be not to
1027
+ # rescue and print the exception, which is
1028
+ # also not yet possible.
253
1029
  # @param [splat] +args+, an splat whose elements are expected to be +blea_args+ and +blocks_args+:
254
1030
  # +blea_args+:: [Array] args to be used internally, which are expected to be:
255
1031
  # +exception_admitted+:: [Boolean]
@@ -261,6 +1037,360 @@ module RubymentModule
261
1037
  end
262
1038
 
263
1039
 
1040
+ end
1041
+
1042
+
1043
+
1044
+ =begin
1045
+ # begin_documentation
1046
+ This module receives only functions that are deprecated.
1047
+ They are still kept in Rubyment, but they won't receive
1048
+ more updates, because there is a different more modern
1049
+ way of achieving the same results.
1050
+ However, functions here are still under active use by
1051
+ some official functions in #RubymentMaintainedModule,
1052
+ which were not yet updated with the new modern way of
1053
+ achieving the same results.
1054
+ # end_documentation
1055
+ =end
1056
+ module RubymentUnderDeprecationModule
1057
+
1058
+
1059
+ include RubymentUnderDeprecationRuneFunctionsModule
1060
+
1061
+
1062
+ end
1063
+
1064
+
1065
+ =begin
1066
+ # begin_documentation
1067
+ This module receives functions that are supposed to test
1068
+ other functions.
1069
+ Eventually, these functions may be run automatically.
1070
+ They must return false if it fails.
1071
+ Eventually a timeouting standard will be set for function
1072
+ doing IO.
1073
+ # end_documentation
1074
+ =end
1075
+ module RubymentTestModule
1076
+
1077
+
1078
+ def test_cases_template args=[]
1079
+ test_cases ||= [
1080
+ # [ :id, :expectation, :actual_params ],
1081
+ # actual_params can be an array with method_name + args to that method.
1082
+ ]
1083
+ end
1084
+
1085
+
1086
+ =begin
1087
+ test for #bled
1088
+ =end
1089
+ def test__bled args=[]
1090
+ test___experiment__bled :bled
1091
+ end
1092
+
1093
+
1094
+ =begin
1095
+ test for #experiment__bled
1096
+ =end
1097
+ def test___experiment__bled args=[]
1098
+ bled_method_name,
1099
+ reserved = args
1100
+ bled_method_name = bled_method_name.nne :experiment__bled
1101
+ p0 = send bled_method_name
1102
+ y0 = p0.first.call 2, 3
1103
+ p1 = send bled_method_name, [] {|x| x}
1104
+ y1 = p1.first.call 2, 3
1105
+ y1_2 = p1.first.call
1106
+ p2 = send bled_method_name, [
1107
+ :default,
1108
+ :no_rescue.negate_me,
1109
+ :yes_output.negate_me,
1110
+ ] {|x| y}
1111
+ y2 = p2.first.call 2, 3
1112
+ p3 = send bled_method_name, [
1113
+ :default,
1114
+ :no_rescue,
1115
+ :yes_output.negate_me,
1116
+ ] {|x| y}
1117
+ y3 = begin
1118
+ p3.first.call 2, 3
1119
+ rescue => e
1120
+ e_info = exception_info_base [e]
1121
+ [:default, e_info, e]
1122
+ end
1123
+
1124
+ judgement =
1125
+ [
1126
+ [y0[0], nil, "no params: return value"],
1127
+ [y0[1].to_a, [], "no params: e_info"],
1128
+ [y0[2], nil, "no params: no exception"],
1129
+
1130
+ [y1[0], 2, "{|x| x}: return value"],
1131
+ [y1[1].to_a, [], "{|x| x}: e_info"],
1132
+ [y1[2], nil, "{|x| x}: no exception"],
1133
+
1134
+ [y1_2[0], nil, "{|x| x}: return value"],
1135
+ [y1_2[1].to_a, [], "{|x| x}: e_info"],
1136
+ [y1_2[2], nil, "{|x| x}: no exception"],
1137
+
1138
+ [y2[0], :default, "default on exception"],
1139
+ [y3[0], y2[0], "exceptions must be the same"],
1140
+ [y3[2].to_s, y2[2].to_s, "exceptions must be the same"],
1141
+ ].map(&method("expect_equal")).all?
1142
+
1143
+ end
1144
+
1145
+
1146
+ =begin
1147
+ test for #call_or_itself
1148
+ =end
1149
+ def test__call_or_itself args=[]
1150
+ method_to_test,
1151
+ reserved = args
1152
+ method_to_test = method_to_test.nne :call_or_itself
1153
+ method_to_send = :array_first_remainder
1154
+ args_to_send = [:arg_to_send_1, :arg_to_send_2, :arg_to_send_3]
1155
+ args_to_bled = []
1156
+
1157
+ send_block = bled(args_to_bled) {
1158
+ self.send method_to_send, args_to_send
1159
+ }.first
1160
+
1161
+ default_block = bled(args_to_bled) {
1162
+ args_to_send
1163
+ }.first
1164
+
1165
+ a1 = (send method_to_test, [send_block, :return_dont_call.negate_me]).first
1166
+ e1 = [:arg_to_send_1, [:arg_to_send_2, :arg_to_send_3]]
1167
+ a2 = (send method_to_test, [default_block, :return_dont_call.negate_me]).first
1168
+ e2 = [:arg_to_send_1, :arg_to_send_2, :arg_to_send_3]
1169
+
1170
+ a3 = send method_to_test, [send_block, :return_dont_call ]
1171
+ e3 = send_block
1172
+ a4 = send method_to_test, [default_block, :return_dont_call ]
1173
+ e4 = default_block
1174
+
1175
+ judgement =
1176
+ [
1177
+ [e1, a1, "#{method_to_test}[send_block, :return_dont_call.negate_me]"],
1178
+ [e2, a2, "#{method_to_test}[default_block, :return_dont_call.negate_me]"],
1179
+ [e3, a3, "#{method_to_test}[send_block, :return_dont_call]"],
1180
+ [e4, a4, "#{method_to_test}[default_block, :return_dont_call]"],
1181
+ ].map(&method("expect_equal")).all?
1182
+ end
1183
+
1184
+
1185
+ =begin
1186
+ test for #experiment__whether
1187
+ =end
1188
+ def test__experiment__whether args=[]
1189
+ method_to_test,
1190
+ reserved = args
1191
+ method_to_test = method_to_test.nne :experiment__whether
1192
+
1193
+ method_to_send = :array_first_remainder
1194
+ args_to_send = [:arg_to_send_1, :arg_to_send_2, :arg_to_send_3]
1195
+ args_to_bled = []
1196
+
1197
+ send_block = bled(args_to_bled) {
1198
+ self.send method_to_send, args_to_send
1199
+ }.first
1200
+
1201
+ default_block = bled(args_to_bled) {
1202
+ args_to_send
1203
+ }.first
1204
+
1205
+ t1 = "two blocks, condition true"
1206
+ a1 = send method_to_test, [
1207
+ method_to_send,
1208
+ send_block,
1209
+ default_block,
1210
+ ]
1211
+ e1 = [[:arg_to_send_1, [:arg_to_send_2, :arg_to_send_3]], nil, nil]
1212
+
1213
+ t2 = "two blocks, condition false"
1214
+ a2 = send method_to_test, [
1215
+ method_to_send.to_nil,
1216
+ send_block,
1217
+ default_block,
1218
+ ]
1219
+ e2 = [[ :arg_to_send_1, :arg_to_send_2, :arg_to_send_3], nil, nil]
1220
+
1221
+ judgement =
1222
+ [
1223
+ [e1, a1, "#{t1}"],
1224
+ [e2, a2, "#{t2}"],
1225
+ ].map(&method("expect_equal")).all?
1226
+ end
1227
+
1228
+
1229
+ =begin
1230
+ =end
1231
+ def test_cases__experiment__send_array_base args=[]
1232
+ method_to_test,
1233
+ reserved = args
1234
+ method_to_test = method_to_test.nne :experiment__send_array_base
1235
+ test_cases ||= [
1236
+ # test_case:
1237
+ [
1238
+ # id:
1239
+ [ "test #{method_to_test} base :array_first_remainder" ],
1240
+ # expectation:
1241
+ [ [ :arg_to_send_1, [:arg_to_send_2, :arg_to_send_3]], nil, nil],
1242
+ # method_name + args:
1243
+ [
1244
+ # method_name:
1245
+ method_to_test,
1246
+ # args to method_to_test:
1247
+ [
1248
+ :array_first_remainder,
1249
+ [ :arg_to_send_1, :arg_to_send_2, :arg_to_send_3 ],
1250
+ ],
1251
+ # array_first_remainder is a function of...
1252
+ self,
1253
+ # debug:
1254
+ 0,
1255
+ ],
1256
+ ],
1257
+
1258
+ ]
1259
+ end
1260
+
1261
+
1262
+ =begin
1263
+ test for #experiment__send_array_base
1264
+ =end
1265
+ def test__experiment__send_array_base args=[]
1266
+ =begin
1267
+ method_to_test,
1268
+ reserved = args
1269
+ method_to_test = method_to_test.nne :experiment__send_array_base
1270
+ e1 = [ [ :arg_to_send_1, [:arg_to_send_2, :arg_to_send_3]], nil, nil]
1271
+ a1 = send method_to_test, [
1272
+ [
1273
+ :array_first_remainder,
1274
+ [ :arg_to_send_1, :arg_to_send_2, :arg_to_send_3 ],
1275
+ ],
1276
+ self,
1277
+ ]
1278
+
1279
+ judgement =
1280
+ [
1281
+ [e1, a1, "test #{method_to_test} base :array_first_remainder"],
1282
+ ].map(&method("expect_equal")).all?
1283
+ =end
1284
+ stderr = @memory[:stderr]
1285
+ debug = debug.nne
1286
+ debug = 1
1287
+ debug && (stderr.puts "{#{__method__} starting")
1288
+ debug && (stderr.puts "caller=#{caller_label}")
1289
+ debug && (stderr.puts backtrace)
1290
+ debug && (stderr.puts "args=#{args.inspect}")
1291
+ test_cases = (test_cases__experiment__send_array_base args)
1292
+ debug && (stderr.puts "test_cases.size=#{test_cases.size}")
1293
+ experiment__tester_block = bled [
1294
+ nil,
1295
+ :no_rescue.negate_me,
1296
+ :output,
1297
+ ] {
1298
+ experiment__tester [
1299
+ (test_cases), 1
1300
+ ]
1301
+ }
1302
+ debug && (stderr.puts "experiment__tester_block=#{experiment__tester_block.inspect}")
1303
+ rv = experiment__tester_block.first.call
1304
+ debug && (stderr.puts "will return #{rv.inspect}")
1305
+ # if raises exception before it will be unbalanced :
1306
+ debug && (stderr.puts "#{__method__} returning}")
1307
+ rv
1308
+ end
1309
+
1310
+
1311
+ end
1312
+
1313
+
1314
+ =begin
1315
+ # begin_documentation
1316
+ This module receives functions that change other
1317
+ Ruby classes, by adding or changing their classes.
1318
+
1319
+ The purpose is normally achieve a more functional
1320
+ approach to some classes.
1321
+
1322
+ Some classes will be changed just by including
1323
+ this file or requiring rubyment, which is not the
1324
+ best approach, but kept to respect the open/closed
1325
+ principle, but new functions should be added here.
1326
+ # end_documentation
1327
+ =end
1328
+ module RubymentClassInjectorModule
1329
+
1330
+
1331
+ end
1332
+
1333
+
1334
+
1335
+ =begin
1336
+ # begin_documentation
1337
+ This module receives all the Rubyment functions.
1338
+
1339
+ Rubyment functions are helper functions to achieve general
1340
+ repetitive programming tasks, including:
1341
+ - Encryption of files or user input with default proper parameters
1342
+ - HTTP/HTTPS server ready-to-go
1343
+ - gem package generation and submission.
1344
+ - tree parsing.
1345
+
1346
+
1347
+ Rubyment functions must respect the open/closed principle
1348
+ (which ensures also "backwards compatibility").
1349
+
1350
+ Rubyment functions rely on a common bus called @memory[:stderr],
1351
+ per process. Any global (or statics, or singleton, or whatever
1352
+ you call it) must be stored there. Any function has complete
1353
+ read-write access to it.
1354
+
1355
+ Rubyment functions normally output debug information to
1356
+ @memory[:stderr] this output
1357
+ is subject to change (ie, not supposed to be parsed, or the
1358
+ parsing may stop working after the function receives maintenance).
1359
+ There is a @memory[;debug] which is no longer much used, nowadays
1360
+ functions are mostly getting a debug parameter to enable locally.
1361
+
1362
+ Output to @memory[:stdout] should be treated as trustworthy, and
1363
+ respect scripts that might parse it. However, if that output comes
1364
+ from a third party command, that output can't be guaranteed
1365
+ (but surely effort will be taken to ensure it won't break consumers).
1366
+
1367
+ README.md contains more standards adopted by Rubyment.
1368
+
1369
+ # end_documentation
1370
+ =end
1371
+ module RubymentModule
1372
+
1373
+ include RubymentClassInjectorModule
1374
+ include RubymentExperimentModule
1375
+ include RubymentMaintainedModule
1376
+ include RubymentDeprecatedModule
1377
+ include RubymentUnderDeprecationModule
1378
+ include RubymentTestModule
1379
+
1380
+
1381
+ # this class very often needs to split
1382
+ # first argument and remaining elements.
1383
+ # args:
1384
+ # args
1385
+ # default:
1386
+ # ARGV
1387
+ # returns:
1388
+ # [ args[0], args[1..-1] ]
1389
+ def array_first_remainder args=ARGV
1390
+ [ args[0], args[1..-1] ]
1391
+ end
1392
+
1393
+
264
1394
  # invoke first arg with following args
265
1395
  # used by initialize
266
1396
  def invoke args=ARGV
@@ -396,9 +1526,11 @@ module RubymentModule
396
1526
  # +headers+:: [Hash] +"Authorization"+ key will be added to it if +auth_user+ is given. Defaults to +{}+
397
1527
  # +method+:: [HTTP method] one of +:get+, +:method+, +:post+ or +:delete+. defaults to +:get+
398
1528
  # +timeout+:: [Fixnum, nil] defaults to +nil+
1529
+ # +debug+:: [Object] if calling the object +nne+ method returns a +false+ value, won't print debug information
399
1530
  #
400
1531
  # @return [String, Object] read data (or +return_on_rescue+)
401
1532
  def file_read args=ARGV
1533
+ stderr = @memory[:stderr]
402
1534
  uri,
403
1535
  username,
404
1536
  password,
@@ -410,13 +1542,18 @@ module RubymentModule
410
1542
  headers,
411
1543
  method,
412
1544
  timeout,
1545
+ debug,
413
1546
  reserved = args
1547
+ debug = debug.nne 1
1548
+ debug && (stderr.puts "{#{__method__} starting")
1549
+ debug && (stderr.puts "args=#{args.inspect}")
414
1550
  uri = uri.nne ""
415
1551
  file_is_directory = File.directory?(uri)
1552
+ must_return_on_rescue = false
416
1553
  return_on_directory_given ||= true
417
1554
  contents = !(file_is_directory) && (
418
1555
  begin
419
- (send :rest_request_or_open_uri_open, [
1556
+ url_response = (send :rest_request_or_open_uri_open, [
420
1557
  uri,
421
1558
  payload,
422
1559
  verify_ssl,
@@ -427,14 +1564,26 @@ module RubymentModule
427
1564
  timeout,
428
1565
  skip_open_uri,
429
1566
  ]).first
1567
+ debug && (stderr.puts "url_response=#{url_response.inspect}")
1568
+ url_response
430
1569
  rescue => e1
431
1570
  begin
1571
+ debug && (stderr.puts "exception e1=#{e1.inspect}")
432
1572
  File.read uri
433
1573
  rescue => e2
1574
+ debug && (stderr.puts "exception e2=#{e2.inspect}")
1575
+ debug && (stderr.puts "return_on_rescue=#{return_on_rescue.inspect}")
1576
+ must_return_on_rescue = true
434
1577
  return_on_rescue
435
1578
  end
436
1579
  end
437
1580
  ) || (file_is_directory) && (return_on_directory_given)
1581
+ rv = contents
1582
+ (rv = return_on_rescue) if must_return_on_rescue
1583
+ debug && (stderr.puts "will return #{rv.inspect}")
1584
+ # if raises exception before it will be unbalanced :
1585
+ debug && (stderr.puts "#{__method__} returning}")
1586
+ rv
438
1587
  end
439
1588
 
440
1589
 
@@ -973,8 +2122,10 @@ module RubymentModule
973
2122
  # +password+:: [String, nil] password for basic authentication method. Will prompt without echo if +nil+ and +auth_user+ is not +nil+
974
2123
  # +timeout+:: [Fixnum, nil] defaults to +nil+
975
2124
  # +skip_open_uri+:: [Boolean] don't bother trying with #open
2125
+ # +debug+:: [Object] if calling the object +nne+ method returns a +false+ value, won't print debug information
976
2126
  # @return [Array] the response
977
2127
  def rest_request_or_open_uri_open args=ARGV
2128
+ stderr = @memory[:stderr]
978
2129
  url,
979
2130
  payload,
980
2131
  verify_ssl,
@@ -984,10 +2135,27 @@ module RubymentModule
984
2135
  password,
985
2136
  timeout,
986
2137
  skip_open_uri,
2138
+ debug,
987
2139
  reserved = args
2140
+
2141
+ debug = debug.nne
2142
+ debug = 1
2143
+ debug && (stderr.puts "{#{__method__} starting")
2144
+ debug && (stderr.puts "args=#{args.inspect}")
988
2145
  skip_open_uri = skip_open_uri.nne
2146
+ debug && (stderr.puts "skip_open_uri=#{skip_open_uri.inspect}")
989
2147
 
990
- response = runea ["yes, rescue",
2148
+ response = runea ["yes, rescue".negate_me,
2149
+ "already not rescuing, forget about output".to_nil,
2150
+ "already not rescuing, forget about return control".to_nil,
2151
+ ] {
2152
+ !skip_open_uri && send(
2153
+ :open,
2154
+ url,
2155
+ :http_basic_authentication => [auth_user, password],
2156
+ ).read
2157
+ }
2158
+ response ||= runea ["yes, rescue",
991
2159
  "output exception".negate_me,
992
2160
  "nil on exception"
993
2161
  ] {
@@ -1002,17 +2170,11 @@ module RubymentModule
1002
2170
  timeout,
1003
2171
  ]
1004
2172
  }
1005
- response ||= runea ["yes, rescue".negate_me,
1006
- "output exception".negate_me,
1007
- "nil on exception"
1008
- ] {
1009
- !skip_open_uri && send(
1010
- :open,
1011
- url,
1012
- :http_basic_authentication => [auth_user, password],
1013
- ).read
1014
- }
1015
- [response]
2173
+ rv = [response]
2174
+ debug && (stderr.puts "#{__method__} will return #{rv.inspect}")
2175
+ # if raises exception before it will be unbalanced :
2176
+ debug && (stderr.puts "#{__method__} returning}")
2177
+ rv
1016
2178
  end
1017
2179
 
1018
2180
 
@@ -2624,16 +3786,16 @@ require '#{gem_name}'
2624
3786
  keep_alive.negate_me && "Connection: close",
2625
3787
  "",
2626
3788
  "#{payload}"
2627
- ].compact
2628
- debug.nne && (stderr.puts "#{__method__} will return #{rv}")
3789
+ ].compact.join eol
3790
+ debug.nne && (stderr.puts "#{__method__} will return \"#{rv}\"")
2629
3791
  debug.nne && (stderr.puts "#{__method__} returning")
2630
- rv.join eol
3792
+ rv
2631
3793
  end
2632
3794
 
2633
3795
 
2634
3796
  =begin
2635
- # documentation_begin
2636
- # short_desc = "tests the function #test__http_response__redirect"
3797
+ # short_desc = "tests function to create an http redirect response "
3798
+
2637
3799
  @memory[:documentation].push = {
2638
3800
  :function => :test__http_response__redirect,
2639
3801
  :short_desc => short_desc,
@@ -2645,6 +3807,42 @@ require '#{gem_name}'
2645
3807
  :duck_type => Array,
2646
3808
  :default_behavior => "interpreted as empty array",
2647
3809
  :params => [
3810
+ {
3811
+ :name => :request,
3812
+ :duck_type => String,
3813
+ :default_behavior => :nil
3814
+ :description => "ignored, will redirect whatever request is made. nil is used.",
3815
+ },
3816
+ {
3817
+ :name => :location,
3818
+ :duck_type => String,
3819
+ :default_behavior => "",
3820
+ :description => "Location: field value (the url to redirect to)",
3821
+ },
3822
+ {
3823
+ :name => :code,
3824
+ :duck_type => String,
3825
+ :default_behavior => "302 Found",
3826
+ :description => "Error code. Note that there are many redirect codes specified by the HTTP protocol.",
3827
+ },
3828
+ {
3829
+ :name => :version,
3830
+ :duck_type => String,
3831
+ :default_behavior => "1.1",
3832
+ :description => "HTTP protocol version",
3833
+ },
3834
+ {
3835
+ :name => :debug,
3836
+ :duck_type => Object,
3837
+ :default_behavior => :nil,
3838
+ :description => "prints debug information to the __IO__ specified by __@memory[:stderr]__ (STDERR by default)",
3839
+ },
3840
+ {
3841
+ :name => :eol,
3842
+ :duck_type => Object,
3843
+ :default_behavior => "\r\n",
3844
+ :description => "separator to join each line of the response",
3845
+ },
2648
3846
  {
2649
3847
  :name => :reserved,
2650
3848
  :duck_type => Object,
@@ -2655,10 +3853,11 @@ require '#{gem_name}'
2655
3853
  },
2656
3854
  ],
2657
3855
  }
2658
- # documentation_end
3856
+
2659
3857
  =end
2660
3858
  def test__http_response__redirect args = []
2661
- location,
3859
+ request,
3860
+ location,
2662
3861
  code,
2663
3862
  version,
2664
3863
  debug,
@@ -2668,12 +3867,10 @@ require '#{gem_name}'
2668
3867
  debug = debug.nne
2669
3868
  debug.nne && (stderr.puts "#{__method__} starting")
2670
3869
  debug.nne && (stderr.puts args.inspect)
2671
- payload ||= ""
2672
- payload = nil
2673
- content_type = nil
2674
- version ||= "1.1"
2675
- code ||= "302 Found"
2676
- eol ||= "\r\n"
3870
+ location = location.nne ""
3871
+ version = version.nne "1.1"
3872
+ code = code.nne "302 Found"
3873
+ eol = eol.nne "\r\n"
2677
3874
  rv = http_response_base [
2678
3875
  :payload.to_nil,
2679
3876
  :content_type.to_nil,
@@ -3536,6 +4733,233 @@ n8mFEtUKobsK
3536
4733
  end
3537
4734
 
3538
4735
 
4736
+ =begin
4737
+ # short_desc = "this functions creates an https (or http server) and a second http server, which always redirect to the first server."
4738
+
4739
+ @memory[:documentation].push = {
4740
+ :function => :experiment__web_http_https_server,
4741
+ :short_desc => short_desc,
4742
+ :description => "",
4743
+ :params => [
4744
+ {
4745
+ :name => :args,
4746
+ :description => "list of parameters",
4747
+ :duck_type => Array,
4748
+ :default_behavior => [],
4749
+ :params => [
4750
+ {
4751
+ :name => :http_processing_method,
4752
+ :duck_type => [:_a, String, :method_name],
4753
+ :default_behavior => :http_OK_response
4754
+ :description => "method name of the method that returns an http request string (used by the first server)",
4755
+ },
4756
+ {
4757
+ :name => :http_processing_method_args,
4758
+ :duck_type => Array,
4759
+ :default_behavior => [],
4760
+ :description => "arguments for the method that returns an http request string (used by the first server)",
4761
+ },
4762
+ {
4763
+ :name => :http_server_port,
4764
+ :duck_type => FixNum,
4765
+ :default_behavior => 8003,
4766
+ :description => " server port (used by the first server)",
4767
+ },
4768
+ {
4769
+ :name => :http_ip_addr,
4770
+ :duck_type => String,
4771
+ :default_behavior => "0",
4772
+ :description => "ip address (used by the first server)",
4773
+ },
4774
+ {
4775
+ :name => :priv_pemfile,
4776
+ :duck_type => String,
4777
+ :default_behavior => ssl_cert_pkey_chain_method[1],
4778
+ :description => "argument to be given to __OpenSSL::SSL::SSLContext.key__ method, after calling __OpenSSL::PKey::RSA.new__ with it. It's the private key file. letsencrypt example: __'/etc/letsencrypt/live/#{domain}/privkey.pem'__ (now it's accepted to pass the file contents instead, both must work).",
4779
+ },
4780
+ {
4781
+ :name => :cert_pem_file,
4782
+ :duck_type => String,
4783
+ :default_behavior => ssl_cert_pkey_chain_method[0],
4784
+ :description => "argument to be given to __OpenSSL::SSL::SSLContext.cert__ method, after calling __OpenSSL::X509::Certificate__. It's the 'Context certificate' accordingly to its ruby-doc page. letsencrypt example: __'/etc/letsencrypt/live/#{domain}/fullchain.pem'__ (now it's accepted to pass the file contents instead, both must work).",
4785
+ },
4786
+ {
4787
+ :name => :extra_cert_pem_files,
4788
+ :duck_type => Object,
4789
+ :duck_type => [:_a, Array, :strings],
4790
+ :default_behavior => ssl_cert_pkey_chain_method[2],
4791
+ :description => "Each string will be mapped with __OpenSSL::SSL::SSLContext.new__, and the resulting array is given to __OpenSSL::SSL::SSLContext.extra_chain_cert__. 'An Array of extra X509 certificates to be added to the certificate chain' accordingly to its ruby-doc. letsencrypt example: __['/etc/letsencrypt/live/#{domain}/chain.pem']__ (now it's accepted to pass the file contents instead, both must work)."
4792
+ },
4793
+ {
4794
+ :name => :ssl_cert_pkey_chain_method,
4795
+ :duck_type => [:_a, String, :method_name],
4796
+ :default_behavior => :ssl_sample_self_signed_cert_encrypted,
4797
+ :description => "method name of the method that returns the certificates (used by the first server)",
4798
+ },
4799
+ {
4800
+ :name => :debug,
4801
+ :duck_type => Object,
4802
+ :default_behavior => :nil,
4803
+ :description => "prints debug information to the __IO__ specified by __@memory[:stderr]__ (STDERR by default)",
4804
+ },
4805
+ {
4806
+ :name => :happy_with_request,
4807
+ :duck_type => String,
4808
+ :default_behavior => nil,
4809
+ :description => "A socket never ends returning data. This variable sets an end to a socket -- after such string is found the socket may be closed. As of this writing, underlying functions will use \r\n if nil is found; this function trusts :io_method to do its best.",
4810
+ },
4811
+ {
4812
+ :name => :io_method,
4813
+ :duck_type => [:_a, String, :method_name],
4814
+ :default_behavior => :io_transform,
4815
+ :description => "method name of the method that reads a socket and forwards the call to a processing method (used both by the first and the redirecting server)",
4816
+ },
4817
+ {
4818
+ :name => :io_method_debug,
4819
+ :duck_type => Object,
4820
+ :default_behavior => :nil,
4821
+ :description => "debug option to the :io_method",
4822
+ },
4823
+ {
4824
+ :name => :admit_non_ssl,
4825
+ :duck_type => Object,
4826
+ :default_behavior => :nil,
4827
+ :description => "if anything fails with the creation of an ssl server, will try to create a plain one (used by the first server)",
4828
+ },
4829
+ {
4830
+ :name => :plain_http_processing_method,
4831
+ :duck_type => [:_a, String, :method_name],
4832
+ :default_behavior => :http_OK_response
4833
+ :description => "method name of the method that returns an http request string (used by the redirecting server)",
4834
+ },
4835
+ {
4836
+ :name => :plain_http_processing_method_args,
4837
+ :duck_type => Array,
4838
+ :default_behavior => [],
4839
+ :description => "arguments for the method that returns an http request string (used by the redirecting server)",
4840
+ },
4841
+ {
4842
+ :name => :plain_http_server_port,
4843
+ :duck_type => FixNum,
4844
+ :default_behavior => 8003,
4845
+ :description => " server port (used by the redirecting server)",
4846
+ },
4847
+ {
4848
+ :name => :plain_http_ip_addr,
4849
+ :duck_type => String,
4850
+ :default_behavior => "0",
4851
+ :description => "ip address (used by the redirect server)",
4852
+ },
4853
+ {
4854
+ :name => :reserved,
4855
+ :duck_type => Object,
4856
+ :default_behavior => :nil,
4857
+ :description => "for future use",
4858
+ },
4859
+ ],
4860
+ },
4861
+ ],
4862
+ }
4863
+ =end
4864
+
4865
+ def experiment__web_http_https_server args = []
4866
+ stderr = @memory[:stderr]
4867
+ http_processing_method,
4868
+ http_processing_method_args,
4869
+ http_server_port,
4870
+ http_ip_addr,
4871
+ priv_pemfile,
4872
+ cert_pem_file,
4873
+ extra_cert_pem_files,
4874
+ ssl_cert_pkey_chain_method,
4875
+ debug,
4876
+ happy_with_request,
4877
+ io_method,
4878
+ io_method_debug,
4879
+ admit_non_ssl,
4880
+ plain_http_processing_method,
4881
+ plain_http_processing_method_args,
4882
+ plain_http_server_port,
4883
+ plain_http_ip_addr,
4884
+ reserved = args
4885
+
4886
+ debug = debug.nne
4887
+ debug.nne && (stderr.puts "{#{__method__} starting")
4888
+ debug && (stderr.puts "args=#{args.inspect}")
4889
+ http_processing_method = http_processing_method.nne :http_OK_response
4890
+ http_processing_method_args = http_processing_method_args.nne []
4891
+ http_server_port = http_server_port.nne 8003
4892
+ redirect_location_host = http_ip_addr.nne "localhost"
4893
+ http_ip_addr = http_ip_addr.nne "0"
4894
+ ssl_cert_pkey_chain_method =
4895
+ ssl_cert_pkey_chain_method.nne :ssl_sample_self_signed_cert_encrypted
4896
+ ssl_cert_pkey_chain = send ssl_cert_pkey_chain_method
4897
+ priv_pemfile = priv_pemfile.nne ssl_cert_pkey_chain[1]
4898
+ cert_pem_file = cert_pem_file.nne ssl_cert_pkey_chain[0]
4899
+ extra_cert_pemiles = extra_cert_pem_files.nne ssl_cert_pkey_chain[2]
4900
+ debug = debug.nne "yes, debug"
4901
+ io_method = io_method.nne "io_transform"
4902
+ io_method_debug = io_method_debug.nne debug
4903
+ happy_with_request = happy_with_request.nne
4904
+ admit_non_ssl = admit_non_ssl.nne
4905
+ plain_http_processing_method = plain_http_processing_method.nne :test__http_response__redirect
4906
+ plain_http_processing_method_args = plain_http_processing_method_args.nne [
4907
+ "https://#{redirect_location_host}:#{http_server_port}/#redirect"
4908
+ ]
4909
+ plain_http_server_port = plain_http_server_port.nne 8004
4910
+ plain_http_ip_addr = plain_http_ip_addr.nne "0"
4911
+
4912
+ tcp_ssl_server_args = [
4913
+ http_server_port,
4914
+ http_ip_addr,
4915
+ debug,
4916
+ admit_non_ssl,
4917
+ io_method,
4918
+ [
4919
+ io_method_debug,
4920
+ happy_with_request,
4921
+ http_processing_method,
4922
+ http_processing_method_args
4923
+ ],
4924
+ priv_pemfile,
4925
+ cert_pem_file,
4926
+ extra_cert_pem_files,
4927
+ "yes, output exceptions",
4928
+ ]
4929
+ tcp_ssl_server_thread = send :tcp_ssl_server, tcp_ssl_server_args
4930
+ tcp_plain_server_args = [
4931
+ plain_http_server_port,
4932
+ plain_http_ip_addr,
4933
+ debug,
4934
+ :admit_non_ssl,
4935
+ io_method,
4936
+ [
4937
+ io_method_debug,
4938
+ happy_with_request,
4939
+ plain_http_processing_method,
4940
+ plain_http_processing_method_args,
4941
+ ],
4942
+ :priv_pemfile.to_nil,
4943
+ :cert_pem_file.to_nil,
4944
+ :extra_cert_pem_files.to_nil,
4945
+ "yes, output exceptions",
4946
+ ]
4947
+ tcp_plain_server_thread = send :tcp_ssl_server, tcp_plain_server_args
4948
+
4949
+ rv = [
4950
+ tcp_ssl_server_thread,
4951
+ tcp_ssl_server_args,
4952
+ :tcp_ssl_server_reserved.to_nil,
4953
+ tcp_plain_server_thread,
4954
+ tcp_plain_server_args,
4955
+ :tcp_ssl_server_reserved.to_nil,
4956
+ ]
4957
+ debug && (stderr.puts "will return #{rv}")
4958
+ debug && (stderr.puts "#{__method__} returning}")
4959
+ rv
4960
+ end
4961
+
4962
+
3539
4963
  # test for tcp_ssl_server (calling an +io_method+,
3540
4964
  # by default #io_transform, with
3541
4965
  # a function that processes an http request and returns
@@ -3601,38 +5025,57 @@ n8mFEtUKobsK
3601
5025
  end
3602
5026
 
3603
5027
 
3604
- # tests file_read against a uri.
3605
- # created to test a client for servers
3606
- # created with
3607
- # #test__tcp_ssl_server__io_method
3608
- def test__file_read__uri_root args = ARGV
5028
+ =begin
5029
+ generalization of #test__file_read__uri_root
5030
+ =end
5031
+ def test__file_read__uri args = []
3609
5032
  stderr = @memory[:stderr]
3610
5033
  domain,
3611
5034
  http_server_port,
3612
5035
  admit_non_ssl,
3613
5036
  debug,
5037
+ path,
3614
5038
  reserved = args
5039
+ debug = debug.nne
5040
+ debug && (stderr.puts "{#{__method__} starting")
5041
+ debug && (stderr.puts "args=#{args.inspect}")
5042
+
3615
5043
  domain = domain.nne "localhost"
5044
+ path = path.nne ""
3616
5045
  http_server_port = http_server_port.nne 8003
3617
5046
  admit_non_ssl = admit_non_ssl.nne true
3618
- debug = debug.nne
3619
- stderr.puts admit_non_ssl.inspect
3620
- stderr.puts (admit_non_ssl && (file_read ["http://#{domain}:#{http_server_port}/"])).inspect
3621
- response = (file_read ["https://#{domain}:#{http_server_port}/"]) ||
3622
- admit_non_ssl && (file_read ["http://#{domain}:#{http_server_port}/"])
3623
- debug && (stderr.puts "response{#{response}}response")
3624
- response
5047
+ http_file_read_attempt = (
5048
+ debug && (stderr.puts "file_read \"https://#{domain}:#{http_server_port}/#{path}\"")
5049
+ file_read ["https://#{domain}:#{http_server_port}/#{path}", nil, nil, :return_on_rescue, nil, :skip_open_uri]
5050
+ )
5051
+ debug && (stderr.puts "#{admit_non_ssl.inspect} && file_read \"http://#{domain}:#{http_server_port}/#{path}\"")
5052
+ response = http_file_read_attempt ||
5053
+ admit_non_ssl && (file_read ["http://#{domain}:#{http_server_port}/#{path}"])
5054
+ rv = [response, http_file_read_attempt]
5055
+ debug && (stderr.puts "#{__method__} will return [response, http_file_read_attempt]=#{rv.inspect}")
5056
+ debug && (stderr.puts "#{__method__} returning}")
5057
+ rv
3625
5058
  end
3626
5059
 
3627
5060
 
3628
- # tests test__tcp_ssl_server__io_method, creating two
3629
- # servers, one ssl and another plain, redirecting to
3630
- # the ssl one. then, opens a client thread with a client
3631
- # connecting to the root document of the plain server
3632
- # (and in the end being served by the root document of
3633
- # the ssl server).
3634
- # another thread for the client
3635
- def test__tcp_ssl_server__get_root__plain_redirect args = ARGV
5061
+ # tests file_read against a uri.
5062
+ # created to test a client for servers
5063
+ # created with
5064
+ # #test__tcp_ssl_server__io_method
5065
+ def test__file_read__uri_root args = ARGV
5066
+ test__file_read__uri args
5067
+ end
5068
+
5069
+
5070
+ =begin
5071
+ tests #experiment__web_http_https_server, creating two
5072
+ servers, one ssl and another plain, redirecting to
5073
+ the ssl one. then, opens a client thread with a client
5074
+ connecting to the root document of the plain server
5075
+ (and in the end being served by the root document of
5076
+ the ssl server).
5077
+ =end
5078
+ def test__experiment__web_http_https_server args = ARGV
3636
5079
  stderr = @memory[:stderr]
3637
5080
  tcp_ssl_server_method,
3638
5081
  http_processing_method,
@@ -3651,11 +5094,11 @@ n8mFEtUKobsK
3651
5094
  admit_non_ssl,
3652
5095
  no_debug_client,
3653
5096
  reserved = args
3654
- tcp_ssl_server_method = tcp_ssl_server_method.nne :test__tcp_ssl_server__io_method
5097
+ tcp_ssl_server_method = tcp_ssl_server_method.nne :experiment__web_http_https_server
3655
5098
  domain = domain.nne "localhost"
3656
5099
  http_server_port = http_server_port.nne 8003
3657
5100
  no_debug_client = no_debug_client.nne
3658
- ssl_server_thread = send tcp_ssl_server_method,
5101
+ servers = send tcp_ssl_server_method,
3659
5102
  [
3660
5103
  http_processing_method,
3661
5104
  http_processing_method_args,
@@ -3672,40 +5115,20 @@ n8mFEtUKobsK
3672
5115
  admit_non_ssl,
3673
5116
  ]
3674
5117
 
3675
- plain_http_processing_method ||= plain_http_processing_method.nne
3676
- plain_http_processing_method_args ||= plain_http_processing_method_args.nne
3677
- plain_http_server_port ||= plain_http_server_port.nne
3678
- plain_http_ip_addr ||= plain_http_ip_addr.nne
3679
-
3680
- plain_server_thread = send tcp_ssl_server_method,
3681
- [
3682
- plain_http_processing_method,
3683
- plain_http_processing_method_args,
3684
- plain_http_server_port,
3685
- plain_http_ip_addr,
3686
- :priv_pemfile.to_nil,
3687
- :cert_pem_file.to_nil,
3688
- :extra_cert_pem_files.to_nil,
3689
- :ssl_cert_pkey_chain_method.to_nil,
3690
- :debug_tcp_ssl_server_method.to_nil,
3691
- happy_with_request,
3692
- plain_io_method,
3693
- plain_io_method_debug,
3694
- :admit_non_ssl,
3695
- ]
3696
-
3697
- thread_2 = Thread.new {
5118
+ # TODO: not hardcoded this way
5119
+ plain_http_server_port = 8004
5120
+ thread_client = Thread.new {
3698
5121
  loop {
3699
5122
  response = test__file_read__uri_root [
3700
5123
  domain,
3701
- http_server_port,
5124
+ plain_http_server_port,
3702
5125
  admit_non_ssl,
3703
- no_debug_client.negate_me,
5126
+ :no_debug_client,
3704
5127
  ]
3705
5128
  sleep 2
3706
5129
  }
3707
5130
  }
3708
- server_thread.first.join
5131
+ servers.first.join
3709
5132
 
3710
5133
  true
3711
5134
  end
@@ -4174,26 +5597,6 @@ n8mFEtUKobsK
4174
5597
  end
4175
5598
 
4176
5599
 
4177
- # generic function for test__ functions
4178
- def test__tester args=[]
4179
- expectation = {}
4180
- actual = {}
4181
- test_cases = args
4182
- test_cases ||= [
4183
- # [ :id, :expectation, :actual_params ],
4184
- ]
4185
- test_cases.each_with_index{ |test_case|
4186
- test_case_id, test_expectation, actual_params = test_case
4187
- result = send actual_params[0], actual_params[1]
4188
- expectation[test_case_id] = test_expectation
4189
- actual[test_case_id] = result
4190
- }
4191
- judgement = actual.keys.map {|test_case|
4192
- [expectation[test_case], actual[test_case] , test_case]
4193
- }.map(&method("expect_equal")).all?
4194
- end
4195
-
4196
-
4197
5600
  # test for #array_unflatten_base_shallow
4198
5601
  def test__array_unflatten_base_shallow args=[]
4199
5602
  test_cases ||= [
@@ -4264,9 +5667,10 @@ n8mFEtUKobsK
4264
5667
  ],
4265
5668
  ],
4266
5669
 
5670
+ # test__array_unflatten_base_shallow
4267
5671
 
4268
5672
  ]
4269
- test__tester test_cases
5673
+ experiment__tester [ test_cases ]
4270
5674
  end
4271
5675
 
4272
5676
 
@@ -4445,16 +5849,16 @@ n8mFEtUKobsK
4445
5849
  ]
4446
5850
  ],
4447
5851
  ],
4448
-
5852
+ # test__array_unflatten_base
4449
5853
 
4450
5854
  ]
4451
- test__tester test_cases
5855
+ experiment__tester [ test_cases ]
4452
5856
  end
4453
5857
 
4454
5858
 
4455
5859
  =begin
4456
- # documentation_begin
4457
5860
  # short_desc = "tests the function #string_repetion"
5861
+
4458
5862
  @memory[:documentation].push = {
4459
5863
  :function => :test__string_repetition,
4460
5864
  :short_desc => short_desc,
@@ -4476,7 +5880,6 @@ n8mFEtUKobsK
4476
5880
  },
4477
5881
  ],
4478
5882
  }
4479
- # documentation_end
4480
5883
 
4481
5884
 
4482
5885
  =end
@@ -4582,9 +5985,53 @@ n8mFEtUKobsK
4582
5985
  end
4583
5986
 
4584
5987
 
5988
+ =begin
5989
+ includes RubymentModule
5990
+ =end
4585
5991
  class Rubyment
4586
5992
  include RubymentModule
4587
5993
  end
5994
+ =begin
5995
+ c = :c
5996
+ experiment__input_select [[:a, :b, :c], c ]
5997
+ =end
5998
+ class Rubyment
5999
+ def experiment__input_select args=[]
6000
+ alternatives,
6001
+ default,
6002
+ reserved = args
6003
+ stderr = @memory[:stderr]
6004
+ caption = alternatives.each_with_index.map {|a, i| "#{i} - #{a.inspect}"}.join("\n")
6005
+ stderr.puts "[alternatives: #{caption}][default: #{default.inspect}]"
6006
+ alternative = input_single_line
6007
+ selection = alternative.nne && alternatives[alternative.to_i] || default
6008
+ end
6009
+ end
6010
+
6011
+
6012
+ =begin
6013
+ =end
6014
+ class Rubyment
6015
+ def file__json args=[]
6016
+ require 'json'
6017
+ file_path,
6018
+ enum,
6019
+ reserved = args
6020
+ File.write file_path, JSON.pretty_generate({ :root.to_s => enum })
6021
+ end
6022
+ def load__file_json args=[]
6023
+ require 'json'
6024
+ file_path,
6025
+ reserved = args
6026
+ file_contents = File.read file_path
6027
+ puts "file_contents size=#{file_contents.size}"
6028
+ loaded = JSON.parse file_contents
6029
+ puts "loaded size=#{loaded.size}"
6030
+ puts "loaded=#{loaded.inspect}"
6031
+ loaded[:root.to_s]
6032
+ end
6033
+ end
6034
+
4588
6035
 
4589
6036
  (__FILE__ == $0) && Rubyment.new({:invoke => ARGV})
4590
6037