qualitysmith_extensions 0.0.3
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 +72 -0
- data/lib/qualitysmith_extensions/all.rb +2 -0
- data/lib/qualitysmith_extensions/array/all.rb +2 -0
- data/lib/qualitysmith_extensions/array/average.rb +42 -0
- data/lib/qualitysmith_extensions/array/expand_ranges.rb +48 -0
- data/lib/qualitysmith_extensions/array/group_by.rb +112 -0
- data/lib/qualitysmith_extensions/array/sequence.rb +64 -0
- data/lib/qualitysmith_extensions/array/shell_escape.rb +34 -0
- data/lib/qualitysmith_extensions/array/to_a_recursive.rb +39 -0
- data/lib/qualitysmith_extensions/array/to_query_string.rb +94 -0
- data/lib/qualitysmith_extensions/collection_extensions_for_cgi.rb +2 -0
- data/lib/qualitysmith_extensions/console/command.facets.1.8.51.rb +749 -0
- data/lib/qualitysmith_extensions/console/command.rb +940 -0
- data/lib/qualitysmith_extensions/date/all.rb +2 -0
- data/lib/qualitysmith_extensions/date/deprecated.rb +38 -0
- data/lib/qualitysmith_extensions/date/iso8601.rb +29 -0
- data/lib/qualitysmith_extensions/date/month_ranges.rb +120 -0
- data/lib/qualitysmith_extensions/enumerable/enum.rb +72 -0
- data/lib/qualitysmith_extensions/file/exact_match_regexp.rb +32 -0
- data/lib/qualitysmith_extensions/file_test/binary_file.rb +108 -0
- data/lib/qualitysmith_extensions/filter_output.rb +107 -0
- data/lib/qualitysmith_extensions/global_variable_set.rb +151 -0
- data/lib/qualitysmith_extensions/hash/all.rb +2 -0
- data/lib/qualitysmith_extensions/hash/to_date.rb +32 -0
- data/lib/qualitysmith_extensions/hash/to_query_string.rb +119 -0
- data/lib/qualitysmith_extensions/kernel/all.rb +2 -0
- data/lib/qualitysmith_extensions/kernel/backtrace.rb +69 -0
- data/lib/qualitysmith_extensions/kernel/capture_output.rb +113 -0
- data/lib/qualitysmith_extensions/kernel/die.rb +34 -0
- data/lib/qualitysmith_extensions/kernel/require_all.rb +118 -0
- data/lib/qualitysmith_extensions/kernel/require_once.rb +16 -0
- data/lib/qualitysmith_extensions/month.rb +62 -0
- data/lib/qualitysmith_extensions/object/singleton.rb +95 -0
- data/lib/qualitysmith_extensions/simulate_input.rb +51 -0
- data/lib/qualitysmith_extensions/string/all.rb +2 -0
- data/lib/qualitysmith_extensions/string/digits_only.rb +25 -0
- data/lib/qualitysmith_extensions/string/md5.rb +27 -0
- data/lib/qualitysmith_extensions/string/shell_escape.rb +41 -0
- data/lib/qualitysmith_extensions/string/to_underscored_label.rb +35 -0
- data/lib/qualitysmith_extensions/test/assert_changed.rb +64 -0
- data/lib/qualitysmith_extensions/test/assert_exception.rb +63 -0
- data/lib/qualitysmith_extensions/test/assert_includes.rb +34 -0
- data/lib/qualitysmith_extensions/test/assert_user_error.rb +34 -0
- data/lib/qualitysmith_extensions/time/all.rb +2 -0
- data/lib/qualitysmith_extensions/time/deprecated.rb +29 -0
- data/test/all.rb +16 -0
- metadata +94 -0
@@ -0,0 +1,38 @@
|
|
1
|
+
# Author:: Tyler Rick
|
2
|
+
# Copyright:: Copyright (c) 2007 QualitySmith, Inc.
|
3
|
+
# License:: Ruby License
|
4
|
+
# Submit to Facets?:: No!
|
5
|
+
|
6
|
+
# Depends on some niceties from ActiveSupport (which really should be in core Ruby but aren't)...
|
7
|
+
require "rubygems"
|
8
|
+
require "active_support"
|
9
|
+
require "pp"
|
10
|
+
|
11
|
+
class Date
|
12
|
+
# These should be moved elsewhere because they are subjective and depend on the context where they're used.
|
13
|
+
def date_for_report
|
14
|
+
strftime("%b %d, %Y") # Example: "Jun 18, 2006"
|
15
|
+
end
|
16
|
+
def month_for_report
|
17
|
+
strftime("%B %Y") # Example: "June 2006"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# _____ _
|
22
|
+
# |_ _|__ ___| |_
|
23
|
+
# | |/ _ \/ __| __|
|
24
|
+
# | | __/\__ \ |_
|
25
|
+
# |_|\___||___/\__|
|
26
|
+
#
|
27
|
+
=begin test
|
28
|
+
class TheTest < Test::Unit::TestCase
|
29
|
+
def test_date_for_report
|
30
|
+
assert_equal 'Jun 18, 2006', Date.new(2006, 6, 18).date_for_report()
|
31
|
+
assert_equal 'Jun 03, 2006', Date.new(2006, 6, 3).date_for_report()
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_month_for_report
|
35
|
+
assert_equal 'June 2006', Date.new(2006, 6).month_for_report()
|
36
|
+
end
|
37
|
+
end
|
38
|
+
=end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# Author:: Tyler Rick
|
2
|
+
# Copyright:: Copyright (c) 2007 QualitySmith, Inc.
|
3
|
+
# License:: Ruby License
|
4
|
+
# Submit to Facets?:: Yes.
|
5
|
+
|
6
|
+
require 'date'
|
7
|
+
require 'rubygems'
|
8
|
+
require 'facets/core/date/to_time'
|
9
|
+
|
10
|
+
class Date
|
11
|
+
def iso8601
|
12
|
+
# Useful for SQL dates, among other things
|
13
|
+
to_time().iso8601()[0..9]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# _____ _
|
18
|
+
# |_ _|__ ___| |_
|
19
|
+
# | |/ _ \/ __| __|
|
20
|
+
# | | __/\__ \ |_
|
21
|
+
# |_|\___||___/\__|
|
22
|
+
#
|
23
|
+
=begin test
|
24
|
+
class TheTest < Test::Unit::TestCase
|
25
|
+
def test_iso8601
|
26
|
+
assert_equal '2006-07-18', Date.civil(2006, 7, 18).iso8601()
|
27
|
+
end
|
28
|
+
end
|
29
|
+
=end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
# Author:: Tyler Rick
|
2
|
+
# Copyright:: Copyright (c) 2007 QualitySmith, Inc.
|
3
|
+
# License:: Ruby License
|
4
|
+
# Submit to Facets?:: Not sure.
|
5
|
+
|
6
|
+
# Depends on some niceties from ActiveSupport (which really should be in core Ruby but aren't)... Date.new(a, b, c)
|
7
|
+
require "rubygems"
|
8
|
+
require "active_support"
|
9
|
+
|
10
|
+
# Attempts in part to make the Date class do everything (or at least some of the things) that the Time class can do (ActiveSupport::CoreExtensions::Time::Calculations).
|
11
|
+
# Maybe that would be better accomplished with a method_missing() that calls to_time.send(:the_same_method) if Time.respond_to?(:that_method).
|
12
|
+
class Date
|
13
|
+
|
14
|
+
# This is based on the implementation of Time.step. The main difference is that it uses
|
15
|
+
# >>= (increment by 1 month) instead of += (increment by 1 day).
|
16
|
+
def month_step(max, step, &block) # { |date| ...}
|
17
|
+
time = self
|
18
|
+
op = [:-,:<=,:>=][step<=>0]
|
19
|
+
while time.__send__(op, max)
|
20
|
+
block.call time
|
21
|
+
time >>= step
|
22
|
+
end
|
23
|
+
self
|
24
|
+
end
|
25
|
+
|
26
|
+
# Step forward one month at a time until we reach max (inclusive), yielding each date as we go
|
27
|
+
def months_upto(max, &block) # { |date| ...}
|
28
|
+
month_step(max, +1, &block)
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_month
|
32
|
+
Month.new(year, month)
|
33
|
+
end
|
34
|
+
|
35
|
+
def next_month
|
36
|
+
# Uses http://api.rubyonrails.org/classes/ActiveSupport/CoreExtensions/Time/Calculations.html#M000336
|
37
|
+
self.to_time.next_month
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
# _____ _
|
43
|
+
# |_ _|__ ___| |_
|
44
|
+
# | |/ _ \/ __| __|
|
45
|
+
# | | __/\__ \ |_
|
46
|
+
# |_|\___||___/\__|
|
47
|
+
#
|
48
|
+
=begin test
|
49
|
+
class TheTest < Test::Unit::TestCase
|
50
|
+
|
51
|
+
#-------------------------------------------------------------------------------------------------
|
52
|
+
# Ranges, step, and upto for *days*
|
53
|
+
# (This is built-in behavior.)
|
54
|
+
|
55
|
+
def test_step
|
56
|
+
list = []
|
57
|
+
collect_as_array = lambda do |date|
|
58
|
+
list << date
|
59
|
+
end
|
60
|
+
|
61
|
+
list = []
|
62
|
+
Date.new(2006, 6, 1).step(Date.new(2006, 6, 3), 1, &collect_as_array)
|
63
|
+
assert_equal [
|
64
|
+
Date.new(2006, 6, 1),
|
65
|
+
Date.new(2006, 6, 2),
|
66
|
+
Date.new(2006, 6, 3)
|
67
|
+
],
|
68
|
+
list
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_range
|
72
|
+
list = Date.new(2006, 6, 1)..Date.new(2006, 6, 3)
|
73
|
+
assert_equal Range.new(Date.new(2006, 6, 1), Date.new(2006, 6, 3)), list
|
74
|
+
end
|
75
|
+
|
76
|
+
#-------------------------------------------------------------------------------------------------
|
77
|
+
# Ranges, step, and upto for *months*
|
78
|
+
|
79
|
+
def test_month_step
|
80
|
+
list = []
|
81
|
+
collect_as_array = lambda do |date|
|
82
|
+
list << date
|
83
|
+
end
|
84
|
+
|
85
|
+
list = []
|
86
|
+
Date.new(2006, 6, 1).month_step(Date.new(2006, 7, 1), 1, &collect_as_array)
|
87
|
+
assert_equal [
|
88
|
+
Date.new(2006, 6, 1),
|
89
|
+
Date.new(2006, 7, 1)
|
90
|
+
],
|
91
|
+
list
|
92
|
+
|
93
|
+
# Test that it ignores days
|
94
|
+
list = []
|
95
|
+
Date.new(2006, 6, 1).month_step(Date.new(2006, 8, 31), 1, &collect_as_array)
|
96
|
+
assert_equal [
|
97
|
+
Date.new(2006, 6, 1),
|
98
|
+
Date.new(2006, 7, 1),
|
99
|
+
Date.new(2006, 8, 1)
|
100
|
+
],
|
101
|
+
list
|
102
|
+
end
|
103
|
+
|
104
|
+
def test_months_upto
|
105
|
+
list = []
|
106
|
+
collect_as_array = lambda do |date|
|
107
|
+
list << date
|
108
|
+
end
|
109
|
+
|
110
|
+
list = []
|
111
|
+
Date.new(2006, 6, 1).months_upto(Date.new(2006, 7, 1), &collect_as_array)
|
112
|
+
assert_equal [
|
113
|
+
Date.new(2006, 6, 1),
|
114
|
+
Date.new(2006, 7, 1)
|
115
|
+
],
|
116
|
+
list
|
117
|
+
end
|
118
|
+
end
|
119
|
+
=end
|
120
|
+
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# Author:: Tyler Rick
|
2
|
+
# Copyright:: Copyright (c) 2007 QualitySmith, Inc.
|
3
|
+
# License:: Ruby License
|
4
|
+
# Submit to Facets?:: Yes!
|
5
|
+
|
6
|
+
require 'enumerator'
|
7
|
+
module Enumerable
|
8
|
+
|
9
|
+
# The core Enumerable module provides the following enumerator methods;
|
10
|
+
# * enum_cons()
|
11
|
+
# * enum_slice()
|
12
|
+
# * enum_with_index()
|
13
|
+
# but for some reason they didn't provide a generic enum() method for the cases they didn't think of!
|
14
|
+
#
|
15
|
+
# +enum+ lets you turn *any* iterator into a general-purpose Enumerator, which, according to the RDocs, is
|
16
|
+
# "A class which provides a method `each' to be used as an Enumerable object."
|
17
|
+
#
|
18
|
+
# This lets you turn any 'each'-type iterator (each_byte, each_line, ...) into a 'map'-type iterator, or into an array, etc.
|
19
|
+
#
|
20
|
+
# So if an object responds to :each_line but not to :map_lines or :lines, you could just do:
|
21
|
+
# object.enum(:each_line).map { block }
|
22
|
+
# object.enum(:each_line).to_a
|
23
|
+
# object.enum(:each_line).min
|
24
|
+
# object.enum(:each_line).grep /pattern/
|
25
|
+
#
|
26
|
+
# If no iterator is specified, :each is assumed:
|
27
|
+
# object.enum.map { block }
|
28
|
+
#
|
29
|
+
# More examples:
|
30
|
+
# Dir.new('.').enum.to_a
|
31
|
+
# #=> ['file1', 'file2']
|
32
|
+
#
|
33
|
+
# "abc".enum(:each_byte).map{|byte| byte.chr.upcase}
|
34
|
+
# #=> ["A", "B", "C"]
|
35
|
+
#
|
36
|
+
def enum(iterator = :each)
|
37
|
+
Enumerable::Enumerator.new(self, iterator)
|
38
|
+
end
|
39
|
+
# Old version, which I don't think was accurate since enum requires obj to be Enumerable as a prerequisite!:
|
40
|
+
#
|
41
|
+
# Lets you add the methods available to Enumerables to any object that responds to :each (or any other iterator).
|
42
|
+
# +enum+ returns a general-purpose Enumerator, which, according to the RDocs, is "A class which provides a method `each' to be used as an Enumerable object."
|
43
|
+
#
|
44
|
+
# This lets you use 'map'-type iterator, for example, on an object that only provides an 'each'-type iterator.
|
45
|
+
# So if an object only responds to :each, but you want to send it :map, you could just do:
|
46
|
+
end
|
47
|
+
|
48
|
+
# _____ _
|
49
|
+
# |_ _|__ ___| |_
|
50
|
+
# | |/ _ \/ __| __|
|
51
|
+
# | | __/\__ \ |_
|
52
|
+
# |_|\___||___/\__|
|
53
|
+
#
|
54
|
+
=begin test
|
55
|
+
require 'test/unit'
|
56
|
+
|
57
|
+
class TheTest < Test::Unit::TestCase
|
58
|
+
def test_1
|
59
|
+
# @options.enum(:each).map { |key, value|
|
60
|
+
# values = [value].flatten
|
61
|
+
# key +
|
62
|
+
# (values.empty? ? " #{flatten.join(' ')}" : '')
|
63
|
+
# }.join(' ')
|
64
|
+
|
65
|
+
# Yes we could use the built-in Array#map method, but...not every class that provides iterators (each, ...) provides a map().
|
66
|
+
assert_equal ['A', 'B', 'C'], ['a', 'b', 'c'].enum(:each).map {|v| v.upcase}
|
67
|
+
end
|
68
|
+
def test_2
|
69
|
+
assert Dir.new('.').enum.to_a.size > 0
|
70
|
+
end
|
71
|
+
end
|
72
|
+
=end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# Author:: Tyler Rick
|
2
|
+
# Copyright:: Copyright (c) 2007 QualitySmith, Inc.
|
3
|
+
# License:: Ruby License
|
4
|
+
# Submit to Facets?:: Yes
|
5
|
+
|
6
|
+
# To do:
|
7
|
+
# * Is there a more object-oriented way to do this? Instance method instead of class method?
|
8
|
+
|
9
|
+
class File
|
10
|
+
def self.exact_match_regexp(filename)
|
11
|
+
/(^|\/)#{Regexp.escape(filename)}$/
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# _____ _
|
16
|
+
# |_ _|__ ___| |_
|
17
|
+
# | |/ _ \/ __| __|
|
18
|
+
# | | __/\__ \ |_
|
19
|
+
# |_|\___||___/\__|
|
20
|
+
#
|
21
|
+
=begin test
|
22
|
+
|
23
|
+
class TheTest < Test::Unit::TestCase
|
24
|
+
def test_1
|
25
|
+
assert 'bar.rb' =~ File.exact_match_regexp('bar.rb')
|
26
|
+
assert '/path/to/bar.rb' =~ File.exact_match_regexp('bar.rb')
|
27
|
+
# But:
|
28
|
+
assert 'foobar.rb' !~ File.exact_match_regexp('bar.rb')
|
29
|
+
end
|
30
|
+
end
|
31
|
+
=end
|
32
|
+
|
@@ -0,0 +1,108 @@
|
|
1
|
+
# Author:: Lloyd Zusman, Tyler Rick
|
2
|
+
# Copyright:: Copyright (c) 2002-2007 Lloyd Zusman
|
3
|
+
# License:: Ruby License
|
4
|
+
# History::
|
5
|
+
# * 2002-10-05: Based on code posted by Lloyd Zusman on ruby-talk on 2002-10-05 (http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/52548)
|
6
|
+
# * 2007-03-15: Cleaned up a bit and wrote tests.
|
7
|
+
# Submit to Facets?:: Yes
|
8
|
+
|
9
|
+
module FileTest
|
10
|
+
|
11
|
+
private
|
12
|
+
def self.is_text?(block)
|
13
|
+
return (block.count("^ -~", "^\b\f\t\r\n") < (block.size / 3.0) &&
|
14
|
+
block.count("\x00") < 1)
|
15
|
+
end
|
16
|
+
|
17
|
+
public
|
18
|
+
# The text_file? and binary_file? methods are not inverses of each other. Both return false if the item is not a file, or if it
|
19
|
+
# is a zero-length file. The "textness" or "binariness" of a file can only be determined if it's a file that contains at least
|
20
|
+
# one byte.
|
21
|
+
|
22
|
+
def self._binary_file?(filename)
|
23
|
+
size = self.size(filename)
|
24
|
+
blksize = File.stat(filename).blksize
|
25
|
+
return nil if !File.file?(filename) || size < 1
|
26
|
+
size = [size, blksize].min
|
27
|
+
begin
|
28
|
+
open(filename) {
|
29
|
+
|file|
|
30
|
+
block = file.read(size)
|
31
|
+
return !self.is_text?(block)
|
32
|
+
}
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.binary_file?(filename)
|
37
|
+
self._binary_file?(filename)
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.text_file?(filename)
|
41
|
+
return_value = self._binary_file?(filename)
|
42
|
+
if return_value.nil?
|
43
|
+
return_value
|
44
|
+
else
|
45
|
+
!return_value
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# _____ _
|
51
|
+
# |_ _|__ ___| |_
|
52
|
+
# | |/ _ \/ __| __|
|
53
|
+
# | | __/\__ \ |_
|
54
|
+
# |_|\___||___/\__|
|
55
|
+
#
|
56
|
+
=begin test
|
57
|
+
require 'test/unit'
|
58
|
+
require 'fileutils'
|
59
|
+
|
60
|
+
class TheTest < Test::Unit::TestCase
|
61
|
+
def empty_file
|
62
|
+
File.open(filename = 'test_file', 'w') do |file|
|
63
|
+
end
|
64
|
+
yield filename
|
65
|
+
ensure
|
66
|
+
FileUtils.rm filename
|
67
|
+
end
|
68
|
+
|
69
|
+
def binary_file
|
70
|
+
File.open(filename = 'test_file', 'wb') do |file|
|
71
|
+
bin_data = [0].pack('c')*(1024)
|
72
|
+
file.write(bin_data)
|
73
|
+
end
|
74
|
+
yield filename
|
75
|
+
ensure
|
76
|
+
FileUtils.rm filename
|
77
|
+
end
|
78
|
+
|
79
|
+
def text_file
|
80
|
+
File.open(filename = 'test_file', 'w') do |file|
|
81
|
+
file.puts('Guten Tag!')
|
82
|
+
end
|
83
|
+
yield filename
|
84
|
+
ensure
|
85
|
+
FileUtils.rm filename
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_empty
|
89
|
+
empty_file do |filename|
|
90
|
+
assert !FileTest.binary_file?(filename)
|
91
|
+
assert !FileTest.text_file?(filename)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
def test_binary
|
95
|
+
binary_file do |filename|
|
96
|
+
assert FileTest.binary_file?(filename)
|
97
|
+
assert !FileTest.text_file?(filename)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
def test_text
|
101
|
+
text_file do |filename|
|
102
|
+
assert !FileTest.binary_file?(filename)
|
103
|
+
assert FileTest.text_file?(filename)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
=end
|
108
|
+
|
@@ -0,0 +1,107 @@
|
|
1
|
+
# Author:: Tyler Rick
|
2
|
+
# Copyright:: Copyright (c) 2007 QualitySmith, Inc.
|
3
|
+
# License:: Ruby License
|
4
|
+
# Submit to Facets?:: Yes.
|
5
|
+
# Developer notes:
|
6
|
+
# * Move to kernel/?
|
7
|
+
|
8
|
+
require 'stringio'
|
9
|
+
|
10
|
+
# Applies +filter+ to any $stderr output that +block+ tries to generate.
|
11
|
+
#
|
12
|
+
# +filter+ should be a Proc that accepts +attempted_output+ as its parameter and returns the string that should _actually_ be output.
|
13
|
+
#
|
14
|
+
# filter_stderr(lambda{''}) do
|
15
|
+
# noisy_command
|
16
|
+
# end
|
17
|
+
def filter_stderr(filter, &block)
|
18
|
+
old_stderr = $stderr
|
19
|
+
$stderr = StringIO.new
|
20
|
+
begin
|
21
|
+
yield
|
22
|
+
ensure
|
23
|
+
what_they_tried_to_output = $stderr.string
|
24
|
+
$stderr = old_stderr
|
25
|
+
$stderr.print filter.call(what_they_tried_to_output)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
def filter_stdout(filter, &block)
|
29
|
+
old_stderr = $stdout
|
30
|
+
$stdout = StringIO.new
|
31
|
+
begin
|
32
|
+
yield
|
33
|
+
ensure
|
34
|
+
what_they_tried_to_output = $stdout.string
|
35
|
+
$stdout = old_stderr
|
36
|
+
$stdout.print filter.call(what_they_tried_to_output)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# _____ _
|
41
|
+
# |_ _|__ ___| |_
|
42
|
+
# | |/ _ \/ __| __|
|
43
|
+
# | | __/\__ \ |_
|
44
|
+
# |_|\___||___/\__|
|
45
|
+
#
|
46
|
+
=begin test
|
47
|
+
require 'test/unit'
|
48
|
+
|
49
|
+
# Not sure whether it's better to duplicate for increased readability or metaprogram for decreased duplication...
|
50
|
+
|
51
|
+
# Duplicate for increased readability:
|
52
|
+
def noisy_command
|
53
|
+
$stderr.puts "Some annoying error message"
|
54
|
+
$stderr.puts "Some error message that we actually care to see"
|
55
|
+
end
|
56
|
+
class TheTest < Test::Unit::TestCase
|
57
|
+
def setup
|
58
|
+
$stderr = StringIO.new
|
59
|
+
end
|
60
|
+
def test_simple_filter
|
61
|
+
filter_stderr(lambda{|input| ''}) do
|
62
|
+
noisy_command
|
63
|
+
end
|
64
|
+
assert_equal '', $stderr.string
|
65
|
+
end
|
66
|
+
def test_sub_filter
|
67
|
+
filter_stderr(Proc.new { |attempted_output|
|
68
|
+
attempted_output.sub(/^Some annoying error message\n/, '')
|
69
|
+
}
|
70
|
+
) do
|
71
|
+
noisy_command
|
72
|
+
end
|
73
|
+
assert_equal "Some error message that we actually care to see\n", $stderr.string
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# Metaprogram for decreased duplication...
|
78
|
+
['stdout', 'stderr'].each do |stream_name|
|
79
|
+
eval(%Q{
|
80
|
+
def noisy_command_#{stream_name}
|
81
|
+
$#{stream_name}.puts "Some annoying error message"
|
82
|
+
$#{stream_name}.puts "Some error message that we actually care to see"
|
83
|
+
end
|
84
|
+
|
85
|
+
class TheTest#{stream_name} < Test::Unit::TestCase
|
86
|
+
def setup
|
87
|
+
$#{stream_name} = StringIO.new
|
88
|
+
end
|
89
|
+
def test_simple_filter
|
90
|
+
filter_#{stream_name}(lambda{|input| ''}) do
|
91
|
+
noisy_command_#{stream_name}
|
92
|
+
end
|
93
|
+
assert_equal '', $#{stream_name}.string
|
94
|
+
end
|
95
|
+
def test_sub_filter
|
96
|
+
filter_#{stream_name}(Proc.new { |attempted_output|
|
97
|
+
attempted_output.sub(/^Some annoying error message\n/, '')
|
98
|
+
}
|
99
|
+
) do
|
100
|
+
noisy_command_#{stream_name}
|
101
|
+
end
|
102
|
+
assert_equal "Some error message that we actually care to see\n", $#{stream_name}.string
|
103
|
+
end
|
104
|
+
end
|
105
|
+
})
|
106
|
+
end
|
107
|
+
=end
|
@@ -0,0 +1,151 @@
|
|
1
|
+
# Author:: Tyler Rick
|
2
|
+
# Copyright:: Copyright (c) 2007 QualitySmith, Inc.
|
3
|
+
# License:: Ruby License
|
4
|
+
# Submit to Facets?:: No, too ugly and unreliable.
|
5
|
+
|
6
|
+
module Kernel
|
7
|
+
# Gets the global variable +var+, which can either be a symbol or an actual global variable (use +:match_object+).
|
8
|
+
# global_variable_get(:$a)
|
9
|
+
# global_variable_get($a, :match_object => true)
|
10
|
+
def global_variable_get(var, options = {})
|
11
|
+
if options.delete(:match_object)
|
12
|
+
return global_variable_get(global_variable_name(var), options)
|
13
|
+
else
|
14
|
+
if var.is_a? Symbol
|
15
|
+
raise NameError.new("#{var} is not a valid global variable name") unless var.to_s[0..0] == '$'
|
16
|
+
return eval("#{var}")
|
17
|
+
else
|
18
|
+
raise ArgumentError.new("var must be a symbol unless :match_object => true")
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Looks up the name of global variable +var+, which must be an actual global variable.
|
24
|
+
# global_variable_name($a)
|
25
|
+
def global_variable_name(var)
|
26
|
+
global_variables.each do |test_var|
|
27
|
+
#if eval(test_var).eql?(var)
|
28
|
+
if eval(test_var).object_id == var.object_id
|
29
|
+
#$stderr.puts "Checking #{test_var}. #{eval(test_var).inspect}"
|
30
|
+
#$stderr.puts " #{$stdout.inspect}"
|
31
|
+
return test_var.to_sym
|
32
|
+
end
|
33
|
+
end
|
34
|
+
raise ArgumentError.new("The given object (#{var.inspect}) (#{var.object_id}) is not a valid global variable")
|
35
|
+
end
|
36
|
+
|
37
|
+
# Sets the global variable +var+, which can either be a symbol or an actual global variable (use +:match_object+).
|
38
|
+
# global_variable_set(:$a, 'new')
|
39
|
+
# global_variable_set($a, 'new', :match_object => true)
|
40
|
+
# global_variable_set(:$a, "StringIO.new", :eval_string => true)
|
41
|
+
def global_variable_set(var, value, options = {})
|
42
|
+
#puts "global_variable_set(#{var}, #{value.inspect}, #{options.inspect}"
|
43
|
+
if options.delete(:match_object)
|
44
|
+
return global_variable_set(global_variable_name(var), value, options)
|
45
|
+
else
|
46
|
+
if var.is_a? Symbol
|
47
|
+
raise NameError.new("#{var} is not a valid global variable name") unless var.to_s[0..0] == '$'
|
48
|
+
if options.delete(:eval_string)
|
49
|
+
#puts("About to eval: #{var} = #{value}")
|
50
|
+
eval("#{var} = #{value}")
|
51
|
+
else
|
52
|
+
marshalled_data = Marshal.dump(value)
|
53
|
+
eval("#{var} = Marshal.load(%Q<#{marshalled_data}>)")
|
54
|
+
end
|
55
|
+
return var
|
56
|
+
else
|
57
|
+
raise ArgumentError.new("var must be a symbol unless :match_object => true")
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# _____ _
|
64
|
+
# |_ _|__ ___| |_
|
65
|
+
# | |/ _ \/ __| __|
|
66
|
+
# | | __/\__ \ |_
|
67
|
+
# |_|\___||___/\__|
|
68
|
+
#
|
69
|
+
=begin test
|
70
|
+
require 'test/unit'
|
71
|
+
require 'stringio'
|
72
|
+
|
73
|
+
class MyClass
|
74
|
+
attr_reader :data
|
75
|
+
@data = [:foo]
|
76
|
+
def ==(other)
|
77
|
+
self.data == other.data
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
class GlobalVariableGetTest < Test::Unit::TestCase
|
82
|
+
def test_simple
|
83
|
+
$a = 'old'
|
84
|
+
assert_equal 'old', global_variable_get(:$a)
|
85
|
+
assert_equal :$a, global_variable_name($a)
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_can_pass_variable_instead_of_symbol
|
89
|
+
$a = 'old'
|
90
|
+
assert_equal 'old', global_variable_get($a, :match_object => true)
|
91
|
+
|
92
|
+
$a = :already_a_symbol
|
93
|
+
assert_raise(NameError) { global_variable_get($a) } # If the global ($a) contains a symbol, it will assume we want to get the global variable *named* :$already_a_symbol . Wrong! That's why the :match_object option was introduced.
|
94
|
+
assert_nothing_raised { global_variable_get($a, :match_object => true) }
|
95
|
+
assert_equal :already_a_symbol, global_variable_get($a, :match_object => true)
|
96
|
+
assert_equal :$a, global_variable_name($a)
|
97
|
+
end
|
98
|
+
|
99
|
+
def test_error
|
100
|
+
assert_raise(NameError) { global_variable_get(:a) } # Must be :$a, not :a
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
class GlobalVariableSetTest < Test::Unit::TestCase
|
105
|
+
def test_simple
|
106
|
+
$a = 'old'
|
107
|
+
global_variable_set(:$a, 'new')
|
108
|
+
assert_equal('new', $a)
|
109
|
+
end
|
110
|
+
|
111
|
+
def test_can_pass_variable_instead_of_symbol
|
112
|
+
$a = 'old'
|
113
|
+
global_variable_set($a, 'new', :match_object => true)
|
114
|
+
assert_equal('new', $a)
|
115
|
+
|
116
|
+
$a = :already_a_symbol
|
117
|
+
assert_raise(NameError) { global_variable_set($a, expected = :a_symbol) } # If the global ($a) contains a symbol, it will assume we want to set the global variable *named* :$already_a_symbol . Wrong! That's why the :match_object option was introduced.
|
118
|
+
assert_nothing_raised { global_variable_set($a, expected = :a_symbol, :match_object => true) }
|
119
|
+
global_variable_set(:$a, expected = :a_symbol)
|
120
|
+
assert_equal(expected, $a)
|
121
|
+
end
|
122
|
+
|
123
|
+
def test_returns_name_of_variable
|
124
|
+
$a = 'old'
|
125
|
+
assert_equal(:$a, global_variable_set(:$a, 'new'))
|
126
|
+
|
127
|
+
$a = 'old'
|
128
|
+
assert_equal(:$a, global_variable_set($a, 'new', :match_object => true))
|
129
|
+
end
|
130
|
+
|
131
|
+
def test_works_for_complex_data_types
|
132
|
+
$a = 'old'
|
133
|
+
global_variable_set(:$a, expected = {:a => 'a', :b => ['1', 2]})
|
134
|
+
assert_equal(expected, $a)
|
135
|
+
|
136
|
+
global_variable_set(:$a, expected = MyClass.new)
|
137
|
+
assert !expected.eql?( $a ) # :bug: The way we do it currently, they'll have different object_id's
|
138
|
+
assert_equal(expected, $a)
|
139
|
+
|
140
|
+
assert_raise(TypeError) { global_variable_set(:$a, expected = $stdout) } # "can't dump IO".
|
141
|
+
assert_raise(TypeError) { global_variable_set(:$a, expected = StringIO.new) } # "no marshal_dump is defined for class StringIO". That's why the :eval_string option was introduced.
|
142
|
+
assert_nothing_raised { global_variable_set(:$a, expected = "StringIO.new", :eval_string => true) }
|
143
|
+
assert $a.is_a?(StringIO)
|
144
|
+
end
|
145
|
+
|
146
|
+
def test_error
|
147
|
+
assert_raise(NameError) { global_variable_set(:a, 'new') } # Must be :$a, not :a
|
148
|
+
end
|
149
|
+
end
|
150
|
+
=end
|
151
|
+
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# Author:: Tyler Rick
|
2
|
+
# Copyright:: Copyright (c) 2007 QualitySmith, Inc.
|
3
|
+
# License:: Ruby License
|
4
|
+
# Submit to Facets?:: Yes. Unless it is deemed not generally reusable enough. Also, only if we can get a Date.new(y,m,d) added to Facets.
|
5
|
+
|
6
|
+
require "rubygems"
|
7
|
+
require "active_support"
|
8
|
+
|
9
|
+
class Hash
|
10
|
+
# Converts a <tt>{:year => ..., :month => ..., :day => ...}</tt> hash into an actual Date object.
|
11
|
+
# Useful for when you have a date element in your <tt>params</tt> hash.
|
12
|
+
def to_date
|
13
|
+
Date.new(fetch(:year).to_i, fetch(:month).to_i, fetch(:day).to_i)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# _____ _
|
18
|
+
# |_ _|__ ___| |_
|
19
|
+
# | |/ _ \/ __| __|
|
20
|
+
# | | __/\__ \ |_
|
21
|
+
# |_|\___||___/\__|
|
22
|
+
#
|
23
|
+
=begin test
|
24
|
+
class TheTest < Test::Unit::TestCase
|
25
|
+
def test_Hash_to_date
|
26
|
+
assert_equal Date.new(2007, 1, 22), {:year => "2007", :month => "01", :day => 22}.to_date
|
27
|
+
end
|
28
|
+
def test_HashWithIndifferentAccess_to_date
|
29
|
+
assert_equal Date.new(2007, 1, 22), HashWithIndifferentAccess.new({:year => "2007", 'month' => 01, :day => 22}).to_date
|
30
|
+
end
|
31
|
+
end
|
32
|
+
=end
|