quality_extensions 0.1.1
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.
- 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
|