quality_extensions 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Readme +54 -0
- data/lib/qualitysmith_extensions/all.rb +4 -0
- data/lib/qualitysmith_extensions/array/all.rb +2 -0
- data/lib/qualitysmith_extensions/array/average.rb +44 -0
- data/lib/qualitysmith_extensions/array/classify.rb +97 -0
- data/lib/qualitysmith_extensions/array/expand_ranges.rb +52 -0
- data/lib/qualitysmith_extensions/array/group_by.rb +134 -0
- data/lib/qualitysmith_extensions/array/sequence.rb +66 -0
- data/lib/qualitysmith_extensions/array/shell_escape.rb +36 -0
- data/lib/qualitysmith_extensions/array/to_a_recursive.rb +41 -0
- data/lib/qualitysmith_extensions/array/to_query_string.rb +96 -0
- data/lib/qualitysmith_extensions/collection_extensions_for_cgi.rb +2 -0
- data/lib/qualitysmith_extensions/colored/toggleability.rb +62 -0
- data/lib/qualitysmith_extensions/console/command.facets.1.8.51.rb +749 -0
- data/lib/qualitysmith_extensions/console/command.facets.1.8.54.rb +748 -0
- data/lib/qualitysmith_extensions/console/command.rb +944 -0
- data/lib/qualitysmith_extensions/date/all.rb +2 -0
- data/lib/qualitysmith_extensions/date/deprecated.rb +40 -0
- data/lib/qualitysmith_extensions/date/iso8601.rb +31 -0
- data/lib/qualitysmith_extensions/date/month_ranges.rb +122 -0
- data/lib/qualitysmith_extensions/dir/each_child.rb +58 -0
- data/lib/qualitysmith_extensions/enumerable/enum.rb +69 -0
- data/lib/qualitysmith_extensions/enumerable/select_until.rb +4 -0
- data/lib/qualitysmith_extensions/enumerable/select_while.rb +109 -0
- data/lib/qualitysmith_extensions/exception/inspect_with_backtrace.rb +65 -0
- data/lib/qualitysmith_extensions/file/exact_match_regexp.rb +34 -0
- data/lib/qualitysmith_extensions/file_test/binary_file.rb +110 -0
- data/lib/qualitysmith_extensions/find/select.rb +68 -0
- data/lib/qualitysmith_extensions/global_variable_set.rb +153 -0
- data/lib/qualitysmith_extensions/hash/all.rb +2 -0
- data/lib/qualitysmith_extensions/hash/to_date.rb +34 -0
- data/lib/qualitysmith_extensions/hash/to_query_string.rb +121 -0
- data/lib/qualitysmith_extensions/kernel/all.rb +2 -0
- data/lib/qualitysmith_extensions/kernel/autoreload.rb +128 -0
- data/lib/qualitysmith_extensions/kernel/backtrace.rb +71 -0
- data/lib/qualitysmith_extensions/kernel/capture_output.rb +115 -0
- data/lib/qualitysmith_extensions/kernel/die.rb +49 -0
- data/lib/qualitysmith_extensions/kernel/example_printer.rb +81 -0
- data/lib/qualitysmith_extensions/kernel/filter_output.rb +108 -0
- data/lib/qualitysmith_extensions/kernel/remove_const.rb +178 -0
- data/lib/qualitysmith_extensions/kernel/remove_module.rb +127 -0
- data/lib/qualitysmith_extensions/kernel/require_all.rb +186 -0
- data/lib/qualitysmith_extensions/kernel/require_local_all.rb +4 -0
- data/lib/qualitysmith_extensions/kernel/require_once.rb +18 -0
- data/lib/qualitysmith_extensions/kernel/simulate_input.rb +52 -0
- data/lib/qualitysmith_extensions/kernel/trap_chain.rb +61 -0
- data/lib/qualitysmith_extensions/kernel/windows_platform.rb +46 -0
- data/lib/qualitysmith_extensions/module/alias_method.rb +6 -0
- data/lib/qualitysmith_extensions/module/alias_method_chain.rb +165 -0
- data/lib/qualitysmith_extensions/module/ancestry_of_instance_method.rb +43 -0
- data/lib/qualitysmith_extensions/module/attribute_accessors.rb +49 -0
- data/lib/qualitysmith_extensions/module/basename.rb +76 -0
- data/lib/qualitysmith_extensions/module/bool_attr_accessor.rb +497 -0
- data/lib/qualitysmith_extensions/module/class_methods.rb +87 -0
- data/lib/qualitysmith_extensions/module/create.rb +315 -0
- data/lib/qualitysmith_extensions/module/create_setter.rb +9 -0
- data/lib/qualitysmith_extensions/module/dirname.rb +4 -0
- data/lib/qualitysmith_extensions/module/guard_method.rb +312 -0
- data/lib/qualitysmith_extensions/module/includable_once.rb +10 -0
- data/lib/qualitysmith_extensions/module/join.rb +66 -0
- data/lib/qualitysmith_extensions/module/malias_method_chain.rb +92 -0
- data/lib/qualitysmith_extensions/module/module_methods.rb +4 -0
- data/lib/qualitysmith_extensions/module/namespace.rb +112 -0
- data/lib/qualitysmith_extensions/module/parents.rb +61 -0
- data/lib/qualitysmith_extensions/module/remove_const.rb +117 -0
- data/lib/qualitysmith_extensions/module/split.rb +55 -0
- data/lib/qualitysmith_extensions/month.rb +66 -0
- data/lib/qualitysmith_extensions/mutex/if_available.rb +75 -0
- data/lib/qualitysmith_extensions/object/ancestry_of_method.rb +257 -0
- data/lib/qualitysmith_extensions/object/default.rb +69 -0
- data/lib/qualitysmith_extensions/object/if_else.rb +157 -0
- data/lib/qualitysmith_extensions/object/ignore_access.rb +84 -0
- data/lib/qualitysmith_extensions/object/mcall.rb +92 -0
- data/lib/qualitysmith_extensions/object/methods.rb +63 -0
- data/lib/qualitysmith_extensions/object/send_if.rb +151 -0
- data/lib/qualitysmith_extensions/object/send_if_not_nil.rb +35 -0
- data/lib/qualitysmith_extensions/object/singleton_send.rb +129 -0
- data/lib/qualitysmith_extensions/regexp/join.rb +111 -0
- data/lib/qualitysmith_extensions/string/all.rb +2 -0
- data/lib/qualitysmith_extensions/string/constantize.rb +4 -0
- data/lib/qualitysmith_extensions/string/digits_only.rb +27 -0
- data/lib/qualitysmith_extensions/string/each_char_with_index.rb +41 -0
- data/lib/qualitysmith_extensions/string/md5.rb +29 -0
- data/lib/qualitysmith_extensions/string/shell_escape.rb +43 -0
- data/lib/qualitysmith_extensions/string/to_underscored_label.rb +37 -0
- data/lib/qualitysmith_extensions/string/with_knowledge_of_color.rb +64 -0
- data/lib/qualitysmith_extensions/symbol/constantize.rb +69 -0
- data/lib/qualitysmith_extensions/symbol/match.rb +157 -0
- data/lib/qualitysmith_extensions/template.rb +33 -0
- data/lib/qualitysmith_extensions/test/all.rb +2 -0
- data/lib/qualitysmith_extensions/test/assert_anything.rb +93 -0
- data/lib/qualitysmith_extensions/test/assert_changed.rb +66 -0
- data/lib/qualitysmith_extensions/test/assert_exception.rb +66 -0
- data/lib/qualitysmith_extensions/test/assert_includes.rb +36 -0
- data/lib/qualitysmith_extensions/test/assert_user_error.rb +37 -0
- data/lib/qualitysmith_extensions/test/difference_highlighting.rb +323 -0
- data/lib/qualitysmith_extensions/time/all.rb +2 -0
- data/lib/qualitysmith_extensions/time/deprecated.rb +31 -0
- data/test/all.rb +16 -0
- metadata +148 -0
@@ -0,0 +1,121 @@
|
|
1
|
+
#--
|
2
|
+
# Author:: Anthony Kaufman, Tyler Rick
|
3
|
+
# Copyright:: Copyright (c) 2007 QualitySmith, Inc.
|
4
|
+
# License:: Ruby License
|
5
|
+
# Submit to Facets?:: Yes.
|
6
|
+
#++
|
7
|
+
|
8
|
+
autoload :CGI, 'cgi'
|
9
|
+
require 'rubygems'
|
10
|
+
require 'facets/core/kernel/require_local'
|
11
|
+
require_local '../array/to_query_string.rb'
|
12
|
+
|
13
|
+
class Hash
|
14
|
+
|
15
|
+
=begin rdoc
|
16
|
+
Converts into a string that can be used as the {query string}[http://en.wikipedia.org/wiki/Query_string] of a URL (for example, <tt>?key1=val1&key2=val2</tt>).
|
17
|
+
|
18
|
+
Example:
|
19
|
+
{
|
20
|
+
'colors' => ['red', 'blue'],
|
21
|
+
'username' => 'pineapple'
|
22
|
+
}.to_query_string('data')
|
23
|
+
==> "data[username]=pineapple&data[colors][]=red&data[colors][]=blue"
|
24
|
+
|
25
|
+
The hash can be nested as deeply as you want and can also contain arrays.
|
26
|
+
|
27
|
+
<tt>key</tt> is the name of the key in params that will receive this hash when you load the page. So, for example, if you go to page with this query string (key = "name"): <tt>?name[first]=Fred&name[last]=Fredson</tt>, params will be have a key "name", like so: <tt>{"name"=>{"last"=>"Fredson", "first"=>"Fred"}}</tt>.
|
28
|
+
|
29
|
+
{
|
30
|
+
'colors' => ['red', 'blue'],
|
31
|
+
'username' => 'pineapple'
|
32
|
+
}.to_query_string('data')
|
33
|
+
|
34
|
+
is equivalent to just writing your hash like so:
|
35
|
+
|
36
|
+
{
|
37
|
+
'data' => {
|
38
|
+
'colors' => ['red', 'blue'],
|
39
|
+
'username' => 'pineapple'
|
40
|
+
}
|
41
|
+
}.to_query_string()
|
42
|
+
=end
|
43
|
+
def to_query_string(key = '')
|
44
|
+
prefix = key.dup
|
45
|
+
elements = []
|
46
|
+
|
47
|
+
self.each_pair do |key, value|
|
48
|
+
key = CGI.escape key.to_s
|
49
|
+
key = prefix.length > 1 ? "#{prefix}[#{key}]" : key
|
50
|
+
if value.respond_to? :to_query_string
|
51
|
+
valuepre = value.dup
|
52
|
+
value = value.to_query_string(key)
|
53
|
+
#puts "#{key}#{valuepre.inspect} => #{value}"
|
54
|
+
elements << value
|
55
|
+
else
|
56
|
+
value = CGI.escape value.to_s
|
57
|
+
elements << key + '=' + value
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
elements.join('&')
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# _____ _
|
66
|
+
# |_ _|__ ___| |_
|
67
|
+
# | |/ _ \/ __| __|
|
68
|
+
# | | __/\__ \ |_
|
69
|
+
# |_|\___||___/\__|
|
70
|
+
#
|
71
|
+
=begin test
|
72
|
+
class TheTest < Test::Unit::TestCase
|
73
|
+
def test_hash_to_query_string_nesting
|
74
|
+
data = {
|
75
|
+
'foo' => 'bar',
|
76
|
+
'names' => {
|
77
|
+
'common' => 'smith',
|
78
|
+
'uncommon' => {
|
79
|
+
:first => 'lance',
|
80
|
+
:last => 'wilheiminkauf'
|
81
|
+
}
|
82
|
+
}
|
83
|
+
}
|
84
|
+
assert_equal 'foo=bar&names[common]=smith&names[uncommon][first]=lance&names[uncommon][last]=wilheiminkauf', data.to_query_string
|
85
|
+
end
|
86
|
+
def test_hash_to_query_string_nesting_2
|
87
|
+
data = {
|
88
|
+
'common' => 'smith',
|
89
|
+
'uncommon' => [
|
90
|
+
'frankenwatzel',
|
91
|
+
'wilheiminkauf'
|
92
|
+
]
|
93
|
+
}
|
94
|
+
assert_equal 'names[common]=smith&names[uncommon][]=frankenwatzel&names[uncommon][]=wilheiminkauf', data.to_query_string('names')
|
95
|
+
assert_equal( {'names' => data}.to_query_string(),
|
96
|
+
data.to_query_string('names') )
|
97
|
+
end
|
98
|
+
|
99
|
+
def test_hash_to_query_string_encoding
|
100
|
+
data = {'f&r' => 'a w$'}
|
101
|
+
|
102
|
+
assert_equal 'f%26r=a+w%24', data.to_query_string
|
103
|
+
end
|
104
|
+
end
|
105
|
+
=end
|
106
|
+
|
107
|
+
=begin examples
|
108
|
+
require 'irb/xmp'
|
109
|
+
xmp <<End
|
110
|
+
{
|
111
|
+
'colors' => ['red', 'blue'],
|
112
|
+
'username' => 'pineapple'
|
113
|
+
}.to_query_string('data')
|
114
|
+
{
|
115
|
+
'data' => {
|
116
|
+
'colors' => ['red', 'blue'],
|
117
|
+
'username' => 'pineapple'
|
118
|
+
}
|
119
|
+
}.to_query_string()
|
120
|
+
End
|
121
|
+
=end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
# CREDIT Michael Neumann
|
2
|
+
# CREDIT George Moschovitis
|
3
|
+
|
4
|
+
module Kernel
|
5
|
+
|
6
|
+
# Autoreload feature files.
|
7
|
+
#
|
8
|
+
# Automatically reload, at regular intervals, any previously loaded features,
|
9
|
+
# and/or other files not already loaded, if they have been modified since the last
|
10
|
+
# interval check. A numeric parameter sets the reload interval in seconds
|
11
|
+
# and the file parameter can either be a glob string or an array
|
12
|
+
# of file paths. If a glob string, it is expanded only once on the initial
|
13
|
+
# method call. Supplying a boolean parameter of 'false' will force autreload to
|
14
|
+
# skip previously loaded features and only reload the specified files.
|
15
|
+
# Also keeps a "dirty" flag.
|
16
|
+
|
17
|
+
def autoreload( *args )
|
18
|
+
|
19
|
+
check_interval=10
|
20
|
+
include_features = true
|
21
|
+
files = nil
|
22
|
+
|
23
|
+
args.each do |arg|
|
24
|
+
case arg
|
25
|
+
when Numeric
|
26
|
+
check_interval = arg
|
27
|
+
when String
|
28
|
+
files = Dir.glob( arg )
|
29
|
+
when Array
|
30
|
+
files = arg
|
31
|
+
when TrueClass, FalseClass
|
32
|
+
include_features = arg
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
file_mtime = {}
|
37
|
+
|
38
|
+
Thread.new(Time.now) do |start_time|
|
39
|
+
loop do
|
40
|
+
sleep check_interval
|
41
|
+
|
42
|
+
if include_features
|
43
|
+
feature_files = $LOADED_FEATURES.collect { |feature|
|
44
|
+
$LOAD_PATH.each { |lp| file = File.join(lp, feature) }
|
45
|
+
}.flatten
|
46
|
+
p feature_files
|
47
|
+
|
48
|
+
feature_files.each { |file|
|
49
|
+
if File.exists?(file) and (mtime = File.stat(file).mtime) > (file_mtime[file] || start_time)
|
50
|
+
$autoreload_dirty = true
|
51
|
+
file_mtime[file] = mtime
|
52
|
+
STDERR.puts "File '#{ file }' reloaded"
|
53
|
+
begin
|
54
|
+
load(file)
|
55
|
+
rescue Exception => e
|
56
|
+
STDERR.puts e.inspect
|
57
|
+
end
|
58
|
+
end
|
59
|
+
}
|
60
|
+
end
|
61
|
+
|
62
|
+
if files
|
63
|
+
files.each do |file|
|
64
|
+
if File.exists?(file) and (mtime = File.stat(file).mtime) > (file_mtime[file] || start_time)
|
65
|
+
$autoreload_dirty = true
|
66
|
+
file_mtime[file] = mtime
|
67
|
+
STDERR.puts "File '#{ file }' changed"
|
68
|
+
begin
|
69
|
+
load(file)
|
70
|
+
rescue Exception => e
|
71
|
+
STDERR.puts e.inspect
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
# Same as #autoreload, but does not include previously loaded features.
|
84
|
+
# This is equivalent to as adding a 'false' parameter to #autoreload.
|
85
|
+
|
86
|
+
def autoreload_files( *args )
|
87
|
+
autoreload( false, *args )
|
88
|
+
end
|
89
|
+
|
90
|
+
# deprecate
|
91
|
+
alias_method :autoreload_glob, :autoreload_files
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
#--
|
96
|
+
# # OLD VERSION
|
97
|
+
# def autoreload(check_interval=10)
|
98
|
+
# Thread.new(Time.now) { |start_time|
|
99
|
+
# file_mtime = {}
|
100
|
+
# loop {
|
101
|
+
# sleep check_interval
|
102
|
+
# $LOADED_FEATURES.each { |feature|
|
103
|
+
# $LOAD_PATH.each { |lp|
|
104
|
+
# file = File.join(lp, feature)
|
105
|
+
# if (File.exists?(file) and
|
106
|
+
# File.stat(file).mtime > (file_mtime[file] || start_time))
|
107
|
+
# file_mtime[file] = File.stat(file).mtime
|
108
|
+
# STDERR.puts "reload #{ file }"
|
109
|
+
# begin
|
110
|
+
# load(file)
|
111
|
+
# rescue Exception => e
|
112
|
+
# STDERR.puts e.inspect
|
113
|
+
# end
|
114
|
+
# end
|
115
|
+
# }
|
116
|
+
# }
|
117
|
+
# }
|
118
|
+
# }
|
119
|
+
# end
|
120
|
+
#++
|
121
|
+
|
122
|
+
# _____ _
|
123
|
+
# |_ _|__ ___| |_
|
124
|
+
# | |/ _ \/ __| __|
|
125
|
+
# | | __/\__ \ |_
|
126
|
+
# |_|\___||___/\__|
|
127
|
+
#
|
128
|
+
# TODO
|
@@ -0,0 +1,71 @@
|
|
1
|
+
#--
|
2
|
+
# Author:: Tyler Rick
|
3
|
+
# Copyright:: Copyright (c) 2007 QualitySmith, Inc.
|
4
|
+
# License:: Ruby License
|
5
|
+
# Submit to Facets?:: Not sure. This might not be necessary if caller() actually works reliably.
|
6
|
+
#++
|
7
|
+
|
8
|
+
require "rubygems"
|
9
|
+
require "facet/string/lines"
|
10
|
+
|
11
|
+
module Kernel
|
12
|
+
# Equivalent to calling caller(0)
|
13
|
+
def backtrace
|
14
|
+
full_backtrace = caller(0)
|
15
|
+
return full_backtrace[1..-1] # We don't want this call to backtrace showing up in the backtrace, so skip top 1 frame.
|
16
|
+
end
|
17
|
+
|
18
|
+
# Returns a human-readable backtrace
|
19
|
+
def pretty_backtrace
|
20
|
+
"Backtrace:\n" +
|
21
|
+
backtrace[1..-1].map{|frame| "* " + frame}.join("\n")
|
22
|
+
end
|
23
|
+
|
24
|
+
# I thought I ran into some case where it didn't work to use caller(0)...which prompted me to do it this way (raise and rescue an exception)...but now I can't duplicate that problem, so I will deprecate this method.
|
25
|
+
def backtrace_using_exception
|
26
|
+
begin
|
27
|
+
raise "Where am I?"
|
28
|
+
rescue Exception => exception
|
29
|
+
full_backtrace = exception.backtrace
|
30
|
+
return full_backtrace[1..-1] # We don't want this call to backtrace showing up in the backtrace, so skip top 1 frame.
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
# _____ _
|
37
|
+
# |_ _|__ ___| |_
|
38
|
+
# | |/ _ \/ __| __|
|
39
|
+
# | | __/\__ \ |_
|
40
|
+
# |_|\___||___/\__|
|
41
|
+
#
|
42
|
+
=begin test
|
43
|
+
class TheTest < Test::Unit::TestCase
|
44
|
+
def test_1_level
|
45
|
+
assert_match /^.*backtrace.rb:\d*:in `test_1_level'$/, backtrace[0]
|
46
|
+
assert_match /^.*testcase.rb:\d*:in `__send__'$/, backtrace[1]
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_pretty_backtrace
|
50
|
+
assert_match /^Backtrace:$/, pretty_backtrace.lines[0]
|
51
|
+
assert_match /^.*backtrace.rb:\d*:in `test_pretty_backtrace'$/, pretty_backtrace.lines[1]
|
52
|
+
assert_match /^.*testcase.rb:\d*:in `__send__'$/, pretty_backtrace.lines[2]
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_2_levels
|
56
|
+
assert_match /^.*backtrace.rb:\d*:in `a_method_that_returns_a_backtrace'$/, a_method_that_returns_a_backtrace[0]
|
57
|
+
assert_match /^.*backtrace.rb:\d*:in `test_2_levels'$/, a_method_that_returns_a_backtrace[1]
|
58
|
+
assert_match /^.*testcase.rb:\d*:in `__send__'$/, a_method_that_returns_a_backtrace[2]
|
59
|
+
end
|
60
|
+
|
61
|
+
def a_method_that_returns_a_backtrace
|
62
|
+
backtrace
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_all_methods_of_getting_backtrace_are_equivalent
|
66
|
+
assert_equal backtrace_using_exception, backtrace
|
67
|
+
assert_equal backtrace_using_exception, caller(0)
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
=end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
#--
|
2
|
+
# Author:: Tyler Rick
|
3
|
+
# Copyright:: Copyright (c) 2007 QualitySmith, Inc.
|
4
|
+
# License:: Ruby License
|
5
|
+
# Submit to Facets?:: Yes
|
6
|
+
#++
|
7
|
+
|
8
|
+
# :todo: Can we find a simpler way to do this based on facets' silence_stream?
|
9
|
+
#
|
10
|
+
# File lib/facets/core/kernel/silence_stream.rb, line 13
|
11
|
+
# def silence_stream(stream)
|
12
|
+
# old_stream = stream.dup
|
13
|
+
# stream.reopen(RUBY_PLATFORM =~ /mswin/ ? 'NUL:' : '/dev/null')
|
14
|
+
# stream.sync = true
|
15
|
+
# yield
|
16
|
+
# ensure
|
17
|
+
# stream.reopen(old_stream)
|
18
|
+
# end
|
19
|
+
|
20
|
+
require 'stringio'
|
21
|
+
require 'rubygems'
|
22
|
+
require 'facets/more/dictionary'
|
23
|
+
|
24
|
+
module Kernel
|
25
|
+
|
26
|
+
# Captures the output (stdout by default) that +block+ tries to generate and returns it as a string.
|
27
|
+
#
|
28
|
+
# output = capture_output($stderr) { noisy_command }
|
29
|
+
#
|
30
|
+
# output = capture_output([$stdout, $stderr]) do
|
31
|
+
# noisy_command
|
32
|
+
# end
|
33
|
+
#
|
34
|
+
# *Note*: If you specify more than one output stream, the entire results of each will be concatenated <i>in the order you listed them</i>, not necessarily in the order that you wrote _to_ those streams.
|
35
|
+
def capture_output(output_streams = $stdout, &block)
|
36
|
+
output_streams = [output_streams] unless output_streams.is_a? Array
|
37
|
+
|
38
|
+
saved_output_streams = Dictionary.new
|
39
|
+
output_streams.each do |output_stream|
|
40
|
+
case output_stream.object_id
|
41
|
+
when $stdout.object_id
|
42
|
+
saved_output_streams[:$stdout] = $stdout
|
43
|
+
$stdout = StringIO.new
|
44
|
+
when $stderr.object_id
|
45
|
+
saved_output_streams[:$stderr] = $stderr
|
46
|
+
$stderr = StringIO.new
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
what_they_tried_to_output = ''
|
51
|
+
begin
|
52
|
+
yield
|
53
|
+
rescue Exception
|
54
|
+
raise
|
55
|
+
ensure
|
56
|
+
saved_output_streams.each do |name, output_stream|
|
57
|
+
case name
|
58
|
+
when :$stdout
|
59
|
+
what_they_tried_to_output += $stdout.string
|
60
|
+
when :$stderr
|
61
|
+
what_they_tried_to_output += $stderr.string
|
62
|
+
end
|
63
|
+
|
64
|
+
# Restore the original output_stream that we saved.
|
65
|
+
case name
|
66
|
+
when :$stdout
|
67
|
+
$stdout = saved_output_streams[:$stdout]
|
68
|
+
when :$stderr
|
69
|
+
$stderr = saved_output_streams[:$stderr]
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
return what_they_tried_to_output
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
# _____ _
|
79
|
+
# |_ _|__ ___| |_
|
80
|
+
# | |/ _ \/ __| __|
|
81
|
+
# | | __/\__ \ |_
|
82
|
+
# |_|\___||___/\__|
|
83
|
+
#
|
84
|
+
=begin test
|
85
|
+
require 'test/unit'
|
86
|
+
|
87
|
+
def noisy_command
|
88
|
+
puts "Some lovely message"
|
89
|
+
$stderr.puts "Some lovely error message"
|
90
|
+
end
|
91
|
+
def noisy_command_with_error
|
92
|
+
puts "Some lovely message"
|
93
|
+
$stderr.puts "Some lovely error message"
|
94
|
+
raise 'an error'
|
95
|
+
end
|
96
|
+
|
97
|
+
class TheTest < Test::Unit::TestCase
|
98
|
+
def test_capture_all
|
99
|
+
assert_equal "Some lovely message\nSome lovely error message\n", capture_output([$stdout, $stderr]) { noisy_command }
|
100
|
+
end
|
101
|
+
def test_capture_all__different_order
|
102
|
+
# This is, I suppose a limitation of StingIO. This behavior may change in a future version if a workaround is found. (Creating a new IO subclass, +TimestampedStringIO+, that keeps a timestamp for every thing you add to it so that the results of two such objects can be merged to yield chronological output.)
|
103
|
+
assert_equal "Some lovely error message\nSome lovely message\n", capture_output([$stderr, $stdout]) { noisy_command }
|
104
|
+
end
|
105
|
+
def test_capture_stdout
|
106
|
+
assert_equal "Some lovely message\n", capture_output($stdout) { noisy_command }
|
107
|
+
end
|
108
|
+
def test_capture_stderr
|
109
|
+
assert_equal "Some lovely error message\n", capture_output($stderr) { noisy_command }
|
110
|
+
end
|
111
|
+
def test_when_an_error_is_raised_from_block
|
112
|
+
assert_raise(RuntimeError) { capture_output() { noisy_command_with_error } }
|
113
|
+
end
|
114
|
+
end
|
115
|
+
=end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
#--
|
2
|
+
# Author:: Tyler Rick
|
3
|
+
# Copyright:: Copyright (c) 2007 QualitySmith, Inc.
|
4
|
+
# License:: Ruby License
|
5
|
+
# Submit to Facets?:: No.
|
6
|
+
# Deprecated. Because I discovered Kernel::abort !
|
7
|
+
#++
|
8
|
+
|
9
|
+
module Kernel
|
10
|
+
def die(message, exit_code = 1)
|
11
|
+
$stderr.puts message
|
12
|
+
exit exit_code
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# _____ _
|
17
|
+
# |_ _|__ ___| |_
|
18
|
+
# | |/ _ \/ __| __|
|
19
|
+
# | | __/\__ \ |_
|
20
|
+
# |_|\___||___/\__|
|
21
|
+
#
|
22
|
+
=begin test
|
23
|
+
require 'rubygems'
|
24
|
+
require 'qualitysmith_extensions/kernel/capture_output'
|
25
|
+
#require 'facets/core/kernel/require_local'
|
26
|
+
#require_local './capture_output'
|
27
|
+
|
28
|
+
class TheTest < Test::Unit::TestCase
|
29
|
+
|
30
|
+
def test_1
|
31
|
+
stderr = capture_output $stderr do
|
32
|
+
assert_raise(SystemExit) do
|
33
|
+
die "Aggh! I'm dying!"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
assert_equal "Aggh! I'm dying!", stderr.chomp
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_abort
|
40
|
+
stderr = capture_output $stderr do
|
41
|
+
assert_raise(SystemExit) do
|
42
|
+
abort "Aggh! I'm dying!"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
assert_equal "Aggh! I'm dying!", stderr.chomp
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
=end
|