rw_fastercsv 1.5.6
Sign up to get free protection for your applications and to get access to all the features.
- data/AUTHORS +1 -0
- data/CHANGELOG +177 -0
- data/COPYING +340 -0
- data/INSTALL +41 -0
- data/LICENSE +7 -0
- data/README +71 -0
- data/Rakefile +93 -0
- data/TODO +6 -0
- data/examples/csv_converters.rb +28 -0
- data/examples/csv_filter.rb +23 -0
- data/examples/csv_rails_import.task +21 -0
- data/examples/csv_reading.rb +57 -0
- data/examples/csv_table.rb +56 -0
- data/examples/csv_writing.rb +67 -0
- data/examples/purchase.csv +3 -0
- data/examples/shortcut_interface.rb +36 -0
- data/lib/faster_csv.rb +2006 -0
- data/lib/fastercsv.rb +10 -0
- data/setup.rb +1360 -0
- data/test/export.csv +5 -0
- data/test/line_endings.gz +0 -0
- data/test/tc_csv_parsing.rb +194 -0
- data/test/tc_csv_writing.rb +96 -0
- data/test/tc_data_converters.rb +260 -0
- data/test/tc_encodings.rb +23 -0
- data/test/tc_features.rb +212 -0
- data/test/tc_headers.rb +277 -0
- data/test/tc_interface.rb +376 -0
- data/test/tc_row.rb +305 -0
- data/test/tc_rp_cases.rb +45 -0
- data/test/tc_serialization.rb +154 -0
- data/test/tc_speed.rb +65 -0
- data/test/tc_table.rb +408 -0
- data/test/test_data.csv +1000 -0
- data/test/ts_all.rb +21 -0
- metadata +97 -0
data/test/export.csv
ADDED
Binary file
|
@@ -0,0 +1,194 @@
|
|
1
|
+
#!/usr/local/bin/ruby -w
|
2
|
+
|
3
|
+
# tc_csv_parsing.rb
|
4
|
+
#
|
5
|
+
# Created by James Edward Gray II on 2005-10-31.
|
6
|
+
# Copyright 2005 Gray Productions. All rights reserved.
|
7
|
+
|
8
|
+
require "test/unit"
|
9
|
+
|
10
|
+
require "faster_csv"
|
11
|
+
|
12
|
+
#
|
13
|
+
# Following tests are my interpretation of the
|
14
|
+
# {CSV RCF}[http://www.ietf.org/rfc/rfc4180.txt]. I only deviate from that
|
15
|
+
# document in one place (intentionally) and that is to make the default row
|
16
|
+
# separator <tt>$/</tt>.
|
17
|
+
#
|
18
|
+
class TestCSVParsing < Test::Unit::TestCase
|
19
|
+
def test_mastering_regex_example
|
20
|
+
ex = %Q{Ten Thousand,10000, 2710 ,,"10,000","It's ""10 Grand"", baby",10K}
|
21
|
+
assert_equal( [ "Ten Thousand", "10000", " 2710 ", nil, "10,000",
|
22
|
+
"It's \"10 Grand\", baby", "10K" ],
|
23
|
+
FasterCSV.parse_line(ex) )
|
24
|
+
end
|
25
|
+
|
26
|
+
# Pulled from: http://www.ruby-lang.org/cgi-bin/cvsweb.cgi/ruby/test/csv/test_csv.rb?rev=1.12.2.2;content-type=text%2Fplain
|
27
|
+
def test_std_lib_csv
|
28
|
+
[ ["\t", ["\t"]],
|
29
|
+
["foo,\"\"\"\"\"\",baz", ["foo", "\"\"", "baz"]],
|
30
|
+
["foo,\"\"\"bar\"\"\",baz", ["foo", "\"bar\"", "baz"]],
|
31
|
+
["\"\"\"\n\",\"\"\"\n\"", ["\"\n", "\"\n"]],
|
32
|
+
["foo,\"\r\n\",baz", ["foo", "\r\n", "baz"]],
|
33
|
+
["\"\"", [""]],
|
34
|
+
["foo,\"\"\"\",baz", ["foo", "\"", "baz"]],
|
35
|
+
["foo,\"\r.\n\",baz", ["foo", "\r.\n", "baz"]],
|
36
|
+
["foo,\"\r\",baz", ["foo", "\r", "baz"]],
|
37
|
+
["foo,\"\",baz", ["foo", "", "baz"]],
|
38
|
+
["\",\"", [","]],
|
39
|
+
["foo", ["foo"]],
|
40
|
+
[",,", [nil, nil, nil]],
|
41
|
+
[",", [nil, nil]],
|
42
|
+
["foo,\"\n\",baz", ["foo", "\n", "baz"]],
|
43
|
+
["foo,,baz", ["foo", nil, "baz"]],
|
44
|
+
["\"\"\"\r\",\"\"\"\r\"", ["\"\r", "\"\r"]],
|
45
|
+
["\",\",\",\"", [",", ","]],
|
46
|
+
["foo,bar,", ["foo", "bar", nil]],
|
47
|
+
[",foo,bar", [nil, "foo", "bar"]],
|
48
|
+
["foo,bar", ["foo", "bar"]],
|
49
|
+
[";", [";"]],
|
50
|
+
["\t,\t", ["\t", "\t"]],
|
51
|
+
["foo,\"\r\n\r\",baz", ["foo", "\r\n\r", "baz"]],
|
52
|
+
["foo,\"\r\n\n\",baz", ["foo", "\r\n\n", "baz"]],
|
53
|
+
["foo,\"foo,bar\",baz", ["foo", "foo,bar", "baz"]],
|
54
|
+
[";,;", [";", ";"]] ].each do |csv_test|
|
55
|
+
assert_equal(csv_test.last, FasterCSV.parse_line(csv_test.first))
|
56
|
+
end
|
57
|
+
|
58
|
+
[ ["foo,\"\"\"\"\"\",baz", ["foo", "\"\"", "baz"]],
|
59
|
+
["foo,\"\"\"bar\"\"\",baz", ["foo", "\"bar\"", "baz"]],
|
60
|
+
["foo,\"\r\n\",baz", ["foo", "\r\n", "baz"]],
|
61
|
+
["\"\"", [""]],
|
62
|
+
["foo,\"\"\"\",baz", ["foo", "\"", "baz"]],
|
63
|
+
["foo,\"\r.\n\",baz", ["foo", "\r.\n", "baz"]],
|
64
|
+
["foo,\"\r\",baz", ["foo", "\r", "baz"]],
|
65
|
+
["foo,\"\",baz", ["foo", "", "baz"]],
|
66
|
+
["foo", ["foo"]],
|
67
|
+
[",,", [nil, nil, nil]],
|
68
|
+
[",", [nil, nil]],
|
69
|
+
["foo,\"\n\",baz", ["foo", "\n", "baz"]],
|
70
|
+
["foo,,baz", ["foo", nil, "baz"]],
|
71
|
+
["foo,bar", ["foo", "bar"]],
|
72
|
+
["foo,\"\r\n\n\",baz", ["foo", "\r\n\n", "baz"]],
|
73
|
+
["foo,\"foo,bar\",baz", ["foo", "foo,bar", "baz"]] ].each do |csv_test|
|
74
|
+
assert_equal(csv_test.last, FasterCSV.parse_line(csv_test.first))
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# From: http://ruby-talk.org/cgi-bin/scat.rb/ruby/ruby-core/6496
|
79
|
+
def test_aras_edge_cases
|
80
|
+
[ [%Q{a,b}, ["a", "b"]],
|
81
|
+
[%Q{a,"""b"""}, ["a", "\"b\""]],
|
82
|
+
[%Q{a,"""b"}, ["a", "\"b"]],
|
83
|
+
[%Q{a,"b"""}, ["a", "b\""]],
|
84
|
+
[%Q{a,"\nb"""}, ["a", "\nb\""]],
|
85
|
+
[%Q{a,"""\nb"}, ["a", "\"\nb"]],
|
86
|
+
[%Q{a,"""\nb\n"""}, ["a", "\"\nb\n\""]],
|
87
|
+
[%Q{a,"""\nb\n""",\nc}, ["a", "\"\nb\n\"", nil]],
|
88
|
+
[%Q{a,,,}, ["a", nil, nil, nil]],
|
89
|
+
[%Q{,}, [nil, nil]],
|
90
|
+
[%Q{"",""}, ["", ""]],
|
91
|
+
[%Q{""""}, ["\""]],
|
92
|
+
[%Q{"""",""}, ["\"",""]],
|
93
|
+
[%Q{,""}, [nil,""]],
|
94
|
+
[%Q{,"\r"}, [nil,"\r"]],
|
95
|
+
[%Q{"\r\n,"}, ["\r\n,"]],
|
96
|
+
[%Q{"\r\n,",}, ["\r\n,", nil]] ].each do |edge_case|
|
97
|
+
assert_equal(edge_case.last, FasterCSV.parse_line(edge_case.first))
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def test_james_edge_cases
|
102
|
+
# A read at eof? should return nil.
|
103
|
+
assert_equal(nil, FasterCSV.parse_line(""))
|
104
|
+
#
|
105
|
+
# With CSV it's impossible to tell an empty line from a line containing a
|
106
|
+
# single +nil+ field. The standard CSV library returns <tt>[nil]</tt>
|
107
|
+
# in these cases, but <tt>Array.new</tt> makes more sense to me.
|
108
|
+
#
|
109
|
+
assert_equal(Array.new, FasterCSV.parse_line("\n1,2,3\n"))
|
110
|
+
end
|
111
|
+
|
112
|
+
def test_rob_edge_cases
|
113
|
+
[ [%Q{"a\nb"}, ["a\nb"]],
|
114
|
+
[%Q{"\n\n\n"}, ["\n\n\n"]],
|
115
|
+
[%Q{a,"b\n\nc"}, ['a', "b\n\nc"]],
|
116
|
+
[%Q{,"\r\n"}, [nil,"\r\n"]],
|
117
|
+
[%Q{,"\r\n."}, [nil,"\r\n."]],
|
118
|
+
[%Q{"a\na","one newline"}, ["a\na", 'one newline']],
|
119
|
+
[%Q{"a\n\na","two newlines"}, ["a\n\na", 'two newlines']],
|
120
|
+
[%Q{"a\r\na","one CRLF"}, ["a\r\na", 'one CRLF']],
|
121
|
+
[%Q{"a\r\n\r\na","two CRLFs"}, ["a\r\n\r\na", 'two CRLFs']],
|
122
|
+
[%Q{with blank,"start\n\nfinish"\n}, ['with blank', "start\n\nfinish"]],
|
123
|
+
].each do |edge_case|
|
124
|
+
assert_equal(edge_case.last, FasterCSV.parse_line(edge_case.first))
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def test_non_regex_edge_cases
|
129
|
+
# An early version of the non-regex parser fails this test
|
130
|
+
[["foo,\"foo,bar,baz,foo\",\"foo\"", ["foo", "foo,bar,baz,foo", "foo"]]].each do |edge_case|
|
131
|
+
assert_equal(edge_case.last, FasterCSV.parse_line(edge_case.first))
|
132
|
+
end
|
133
|
+
|
134
|
+
assert_raise(FasterCSV::MalformedCSVError) do
|
135
|
+
FasterCSV.parse_line("1,\"23\"4\"5\", 6")
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def test_malformed_csv
|
140
|
+
assert_raise(FasterCSV::MalformedCSVError) do
|
141
|
+
FasterCSV.parse_line("1,2\r,3", :row_sep => "\n")
|
142
|
+
end
|
143
|
+
|
144
|
+
bad_data = <<-END_DATA.gsub(/^ +/, "")
|
145
|
+
line,1,abc
|
146
|
+
line,2,"def\nghi"
|
147
|
+
|
148
|
+
line,4,some\rjunk
|
149
|
+
line,5,jkl
|
150
|
+
END_DATA
|
151
|
+
lines = bad_data.to_a
|
152
|
+
assert_equal(6, lines.size)
|
153
|
+
assert_match(/\Aline,4/, lines.find { |l| l =~ /some\rjunk/ })
|
154
|
+
|
155
|
+
csv = FasterCSV.new(bad_data)
|
156
|
+
begin
|
157
|
+
loop do
|
158
|
+
assert_not_nil(csv.shift)
|
159
|
+
assert_send([csv.lineno, :<, 4])
|
160
|
+
end
|
161
|
+
rescue FasterCSV::MalformedCSVError
|
162
|
+
assert_equal( "Unquoted fields do not allow \\r or \\n (line 4).",
|
163
|
+
$!.message )
|
164
|
+
end
|
165
|
+
|
166
|
+
assert_nothing_raised(FasterCSV::MalformedCSVError) do
|
167
|
+
FasterCSV.parse_line('1,2,"3...',{:raise_exception => false})
|
168
|
+
end
|
169
|
+
assert_raise(FasterCSV::MalformedCSVError) do
|
170
|
+
FasterCSV.parse_line('1,2,"3...')
|
171
|
+
end
|
172
|
+
|
173
|
+
bad_data = <<-END_DATA.gsub(/^ +/, "")
|
174
|
+
line,1,abc
|
175
|
+
line,2,"def\nghi"
|
176
|
+
|
177
|
+
line,4,8'10"
|
178
|
+
line,5,jkl
|
179
|
+
END_DATA
|
180
|
+
lines = bad_data.to_a
|
181
|
+
assert_equal(6, lines.size)
|
182
|
+
assert_match(/\Aline,4/, lines.find { |l| l =~ /8'10"/ })
|
183
|
+
|
184
|
+
csv = FasterCSV.new(bad_data)
|
185
|
+
begin
|
186
|
+
loop do
|
187
|
+
assert_not_nil(csv.shift)
|
188
|
+
assert_send([csv.lineno, :<, 4])
|
189
|
+
end
|
190
|
+
rescue FasterCSV::MalformedCSVError
|
191
|
+
assert_equal("Illegal quoting on line 4.", $!.message)
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
#!/usr/local/bin/ruby -w
|
2
|
+
|
3
|
+
# tc_csv_writing.rb
|
4
|
+
#
|
5
|
+
# Created by James Edward Gray II on 2005-11-14.
|
6
|
+
# Copyright 2005 Gray Productions. All rights reserved.
|
7
|
+
|
8
|
+
require "test/unit"
|
9
|
+
|
10
|
+
require "faster_csv"
|
11
|
+
|
12
|
+
class TestFasterCSVWriting < Test::Unit::TestCase
|
13
|
+
def test_writing
|
14
|
+
[ ["\t", ["\t"]],
|
15
|
+
["foo,\"\"\"\"\"\",baz", ["foo", "\"\"", "baz"]],
|
16
|
+
["foo,\"\"\"bar\"\"\",baz", ["foo", "\"bar\"", "baz"]],
|
17
|
+
["\"\"\"\n\",\"\"\"\n\"", ["\"\n", "\"\n"]],
|
18
|
+
["foo,\"\r\n\",baz", ["foo", "\r\n", "baz"]],
|
19
|
+
["\"\"", [""]],
|
20
|
+
["foo,\"\"\"\",baz", ["foo", "\"", "baz"]],
|
21
|
+
["foo,\"\r.\n\",baz", ["foo", "\r.\n", "baz"]],
|
22
|
+
["foo,\"\r\",baz", ["foo", "\r", "baz"]],
|
23
|
+
["foo,\"\",baz", ["foo", "", "baz"]],
|
24
|
+
["\",\"", [","]],
|
25
|
+
["foo", ["foo"]],
|
26
|
+
[",,", [nil, nil, nil]],
|
27
|
+
[",", [nil, nil]],
|
28
|
+
["foo,\"\n\",baz", ["foo", "\n", "baz"]],
|
29
|
+
["foo,,baz", ["foo", nil, "baz"]],
|
30
|
+
["\"\"\"\r\",\"\"\"\r\"", ["\"\r", "\"\r"]],
|
31
|
+
["\",\",\",\"", [",", ","]],
|
32
|
+
["foo,bar,", ["foo", "bar", nil]],
|
33
|
+
[",foo,bar", [nil, "foo", "bar"]],
|
34
|
+
["foo,bar", ["foo", "bar"]],
|
35
|
+
[";", [";"]],
|
36
|
+
["\t,\t", ["\t", "\t"]],
|
37
|
+
["foo,\"\r\n\r\",baz", ["foo", "\r\n\r", "baz"]],
|
38
|
+
["foo,\"\r\n\n\",baz", ["foo", "\r\n\n", "baz"]],
|
39
|
+
["foo,\"foo,bar\",baz", ["foo", "foo,bar", "baz"]],
|
40
|
+
[";,;", [";", ";"]],
|
41
|
+
["foo,\"\"\"\"\"\",baz", ["foo", "\"\"", "baz"]],
|
42
|
+
["foo,\"\"\"bar\"\"\",baz", ["foo", "\"bar\"", "baz"]],
|
43
|
+
["foo,\"\r\n\",baz", ["foo", "\r\n", "baz"]],
|
44
|
+
["\"\"", [""]],
|
45
|
+
["foo,\"\"\"\",baz", ["foo", "\"", "baz"]],
|
46
|
+
["foo,\"\r.\n\",baz", ["foo", "\r.\n", "baz"]],
|
47
|
+
["foo,\"\r\",baz", ["foo", "\r", "baz"]],
|
48
|
+
["foo,\"\",baz", ["foo", "", "baz"]],
|
49
|
+
["foo", ["foo"]],
|
50
|
+
[",,", [nil, nil, nil]],
|
51
|
+
[",", [nil, nil]],
|
52
|
+
["foo,\"\n\",baz", ["foo", "\n", "baz"]],
|
53
|
+
["foo,,baz", ["foo", nil, "baz"]],
|
54
|
+
["foo,bar", ["foo", "bar"]],
|
55
|
+
["foo,\"\r\n\n\",baz", ["foo", "\r\n\n", "baz"]],
|
56
|
+
["foo,\"foo,bar\",baz", ["foo", "foo,bar", "baz"]],
|
57
|
+
[%Q{a,b}, ["a", "b"]],
|
58
|
+
[%Q{a,"""b"""}, ["a", "\"b\""]],
|
59
|
+
[%Q{a,"""b"}, ["a", "\"b"]],
|
60
|
+
[%Q{a,"b"""}, ["a", "b\""]],
|
61
|
+
[%Q{a,"\nb"""}, ["a", "\nb\""]],
|
62
|
+
[%Q{a,"""\nb"}, ["a", "\"\nb"]],
|
63
|
+
[%Q{a,"""\nb\n"""}, ["a", "\"\nb\n\""]],
|
64
|
+
[%Q{a,"""\nb\n""",}, ["a", "\"\nb\n\"", nil]],
|
65
|
+
[%Q{a,,,}, ["a", nil, nil, nil]],
|
66
|
+
[%Q{,}, [nil, nil]],
|
67
|
+
[%Q{"",""}, ["", ""]],
|
68
|
+
[%Q{""""}, ["\""]],
|
69
|
+
[%Q{"""",""}, ["\"",""]],
|
70
|
+
[%Q{,""}, [nil,""]],
|
71
|
+
[%Q{,"\r"}, [nil,"\r"]],
|
72
|
+
[%Q{"\r\n,"}, ["\r\n,"]],
|
73
|
+
[%Q{"\r\n,",}, ["\r\n,", nil]] ].each do |test_case|
|
74
|
+
assert_equal( test_case.first + $/,
|
75
|
+
FasterCSV.generate_line(test_case.last) )
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_col_sep
|
80
|
+
assert_equal( "a;b;;c\n", FasterCSV.generate_line( ["a", "b", nil, "c"],
|
81
|
+
:col_sep => ";" ) )
|
82
|
+
assert_equal( "a\tb\t\tc\n", FasterCSV.generate_line( ["a", "b", nil, "c"],
|
83
|
+
:col_sep => "\t" ) )
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_row_sep
|
87
|
+
assert_equal( "a,b,,c\r\n", FasterCSV.generate_line( ["a", "b", nil, "c"],
|
88
|
+
:row_sep => "\r\n" ) )
|
89
|
+
end
|
90
|
+
|
91
|
+
def test_force_quotes
|
92
|
+
assert_equal( %Q{"1","b","","already ""quoted"""\n},
|
93
|
+
FasterCSV.generate_line( [1, "b", nil, %Q{already "quoted"}],
|
94
|
+
:force_quotes => true ) )
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,260 @@
|
|
1
|
+
#!/usr/local/bin/ruby -w
|
2
|
+
|
3
|
+
# tc_data_converters.rb
|
4
|
+
#
|
5
|
+
# Created by James Edward Gray II on 2005-12-30.
|
6
|
+
# Copyright 2005 Gray Productions. All rights reserved.
|
7
|
+
|
8
|
+
require "test/unit"
|
9
|
+
|
10
|
+
require "faster_csv"
|
11
|
+
|
12
|
+
class TestDataConverters < Test::Unit::TestCase
|
13
|
+
def setup
|
14
|
+
@data = "Numbers,:integer,1,:float,3.015"
|
15
|
+
@parser = FasterCSV.new(@data)
|
16
|
+
|
17
|
+
@custom = lambda { |field| field =~ /\A:(\S.*?)\s*\Z/ ? $1.to_sym : field }
|
18
|
+
|
19
|
+
@win_safe_time_str = Time.now.strftime("%a %b %d %H:%M:%S %Y")
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_builtin_integer_converter
|
23
|
+
# does convert
|
24
|
+
[-5, 1, 10000000000].each do |n|
|
25
|
+
assert_equal(n, FasterCSV::Converters[:integer][n.to_s])
|
26
|
+
end
|
27
|
+
|
28
|
+
# does not convert
|
29
|
+
(%w{junk 1.0} + [""]).each do |str|
|
30
|
+
assert_equal(str, FasterCSV::Converters[:integer][str])
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_builtin_float_converter
|
35
|
+
# does convert
|
36
|
+
[-5.1234, 0, 2.3e-11].each do |n|
|
37
|
+
assert_equal(n, FasterCSV::Converters[:float][n.to_s])
|
38
|
+
end
|
39
|
+
|
40
|
+
# does not convert
|
41
|
+
(%w{junk 1..0 .015F} + [""]).each do |str|
|
42
|
+
assert_equal(str, FasterCSV::Converters[:float][str])
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_builtin_date_converter
|
47
|
+
# does convert
|
48
|
+
assert_instance_of(
|
49
|
+
Date,
|
50
|
+
FasterCSV::Converters[:date][@win_safe_time_str.sub(/\d+:\d+:\d+ /, "")]
|
51
|
+
)
|
52
|
+
|
53
|
+
# does not convert
|
54
|
+
assert_instance_of(String, FasterCSV::Converters[:date]["junk"])
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_builtin_date_time_converter
|
58
|
+
# does convert
|
59
|
+
assert_instance_of( DateTime,
|
60
|
+
FasterCSV::Converters[:date_time][@win_safe_time_str] )
|
61
|
+
|
62
|
+
# does not convert
|
63
|
+
assert_instance_of(String, FasterCSV::Converters[:date_time]["junk"])
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_convert_with_builtin
|
67
|
+
# setup parser...
|
68
|
+
assert(@parser.respond_to?(:convert))
|
69
|
+
assert_nothing_raised(Exception) { @parser.convert(:integer) }
|
70
|
+
|
71
|
+
# and use
|
72
|
+
assert_equal(["Numbers", ":integer", 1, ":float", "3.015"], @parser.shift)
|
73
|
+
|
74
|
+
setup # reset
|
75
|
+
|
76
|
+
# setup parser...
|
77
|
+
assert_nothing_raised(Exception) { @parser.convert(:float) }
|
78
|
+
|
79
|
+
# and use
|
80
|
+
assert_equal(["Numbers", ":integer", 1.0, ":float", 3.015], @parser.shift)
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_convert_order
|
84
|
+
# floats first, then integers...
|
85
|
+
assert_nothing_raised(Exception) do
|
86
|
+
@parser.convert(:float)
|
87
|
+
@parser.convert(:integer)
|
88
|
+
end
|
89
|
+
|
90
|
+
# gets us nothing but floats
|
91
|
+
assert_equal( [String, String, Float, String, Float],
|
92
|
+
@parser.shift.map { |field| field.class } )
|
93
|
+
|
94
|
+
setup # reset
|
95
|
+
|
96
|
+
# integers have precendance...
|
97
|
+
assert_nothing_raised(Exception) do
|
98
|
+
@parser.convert(:integer)
|
99
|
+
@parser.convert(:float)
|
100
|
+
end
|
101
|
+
|
102
|
+
# gives us proper number conversion
|
103
|
+
assert_equal( [String, String, Fixnum, String, Float],
|
104
|
+
@parser.shift.map { |field| field.class } )
|
105
|
+
end
|
106
|
+
|
107
|
+
def test_builtin_numeric_combo_converter
|
108
|
+
# setup parser...
|
109
|
+
assert_nothing_raised(Exception) { @parser.convert(:numeric) }
|
110
|
+
|
111
|
+
# and use
|
112
|
+
assert_equal( [String, String, Fixnum, String, Float],
|
113
|
+
@parser.shift.map { |field| field.class } )
|
114
|
+
end
|
115
|
+
|
116
|
+
def test_builtin_all_nested_combo_converter
|
117
|
+
# setup parser...
|
118
|
+
@data << ",#{@win_safe_time_str}" # add a DateTime field
|
119
|
+
@parser = FasterCSV.new(@data) # reset parser
|
120
|
+
assert_nothing_raised(Exception) { @parser.convert(:all) }
|
121
|
+
|
122
|
+
# and use
|
123
|
+
assert_equal( [String, String, Fixnum, String, Float, DateTime],
|
124
|
+
@parser.shift.map { |field| field.class } )
|
125
|
+
end
|
126
|
+
|
127
|
+
def test_convert_with_custom_code
|
128
|
+
# define custom converter...
|
129
|
+
assert_nothing_raised(Exception) do
|
130
|
+
@parser.convert { |field| field =~ /\A:(\S.*?)\s*\Z/ ? $1.to_sym : field }
|
131
|
+
end
|
132
|
+
|
133
|
+
# and use
|
134
|
+
assert_equal(["Numbers", :integer, "1", :float, "3.015"], @parser.shift)
|
135
|
+
|
136
|
+
setup # reset
|
137
|
+
|
138
|
+
# mix built-in and custom...
|
139
|
+
assert_nothing_raised(Exception) { @parser.convert(:numeric) }
|
140
|
+
assert_nothing_raised(Exception) { @parser.convert(&@custom) }
|
141
|
+
|
142
|
+
# and use
|
143
|
+
assert_equal(["Numbers", :integer, 1, :float, 3.015], @parser.shift)
|
144
|
+
end
|
145
|
+
|
146
|
+
def test_convert_with_custom_code_using_field_info
|
147
|
+
# define custom converter that uses field information...
|
148
|
+
assert_nothing_raised(Exception) do
|
149
|
+
@parser.convert do |field, info|
|
150
|
+
assert_equal(1, info.line)
|
151
|
+
info.index == 4 ? Float(field).floor : field
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
# and use
|
156
|
+
assert_equal(["Numbers", ":integer", "1", ":float", 3], @parser.shift)
|
157
|
+
end
|
158
|
+
|
159
|
+
def test_convert_with_custom_code_using_field_info_header
|
160
|
+
@parser = FasterCSV.new(@data, :headers => %w{one two three four five})
|
161
|
+
|
162
|
+
# define custom converter that uses field header information...
|
163
|
+
assert_nothing_raised(Exception) do
|
164
|
+
@parser.convert do |field, info|
|
165
|
+
info.header == "three" ? Integer(field) * 100 : field
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
# and use
|
170
|
+
assert_equal(["Numbers", ":integer", 100, ":float", "3.015"], @parser.shift.fields)
|
171
|
+
end
|
172
|
+
|
173
|
+
def test_shortcut_interface
|
174
|
+
assert_equal( ["Numbers", ":integer", 1, ":float", 3.015],
|
175
|
+
FasterCSV.parse_line(@data, :converters => :numeric) )
|
176
|
+
|
177
|
+
assert_equal( ["Numbers", ":integer", 1, ":float", 3.015],
|
178
|
+
FasterCSV.parse_line( @data, :converters => [ :integer,
|
179
|
+
:float ] ) )
|
180
|
+
|
181
|
+
assert_equal( ["Numbers", :integer, 1, :float, 3.015],
|
182
|
+
FasterCSV.parse_line( @data, :converters => [ :numeric,
|
183
|
+
@custom ] ) )
|
184
|
+
end
|
185
|
+
|
186
|
+
def test_unconverted_fields
|
187
|
+
[ [ @data,
|
188
|
+
["Numbers", :integer, 1, :float, 3.015],
|
189
|
+
%w{Numbers :integer 1 :float 3.015} ],
|
190
|
+
["\n", Array.new, Array.new] ].each do |test, fields, unconverted|
|
191
|
+
row = nil
|
192
|
+
assert_nothing_raised(Exception) do
|
193
|
+
row = FasterCSV.parse_line( test,
|
194
|
+
:converters => [:numeric, @custom],
|
195
|
+
:unconverted_fields => true )
|
196
|
+
end
|
197
|
+
assert_not_nil(row)
|
198
|
+
assert_equal(fields, row)
|
199
|
+
assert_respond_to(row, :unconverted_fields)
|
200
|
+
assert_equal(unconverted, row.unconverted_fields)
|
201
|
+
end
|
202
|
+
|
203
|
+
data = <<-END_CSV.gsub(/^\s+/, "")
|
204
|
+
first,second,third
|
205
|
+
1,2,3
|
206
|
+
END_CSV
|
207
|
+
row = nil
|
208
|
+
assert_nothing_raised(Exception) do
|
209
|
+
row = FasterCSV.parse_line( data,
|
210
|
+
:converters => :numeric,
|
211
|
+
:unconverted_fields => true,
|
212
|
+
:headers => :first_row )
|
213
|
+
end
|
214
|
+
assert_not_nil(row)
|
215
|
+
assert_equal([["first", 1], ["second", 2], ["third", 3]], row.to_a)
|
216
|
+
assert_respond_to(row, :unconverted_fields)
|
217
|
+
assert_equal(%w{1 2 3}, row.unconverted_fields)
|
218
|
+
|
219
|
+
assert_nothing_raised(Exception) do
|
220
|
+
row = FasterCSV.parse_line( data,
|
221
|
+
:converters => :numeric,
|
222
|
+
:unconverted_fields => true,
|
223
|
+
:headers => :first_row,
|
224
|
+
:return_headers => true )
|
225
|
+
end
|
226
|
+
assert_not_nil(row)
|
227
|
+
assert_equal( [%w{first first}, %w{second second}, %w{third third}],
|
228
|
+
row.to_a )
|
229
|
+
assert_respond_to(row, :unconverted_fields)
|
230
|
+
assert_equal(%w{first second third}, row.unconverted_fields)
|
231
|
+
|
232
|
+
assert_nothing_raised(Exception) do
|
233
|
+
row = FasterCSV.parse_line( data,
|
234
|
+
:converters => :numeric,
|
235
|
+
:unconverted_fields => true,
|
236
|
+
:headers => :first_row,
|
237
|
+
:return_headers => true,
|
238
|
+
:header_converters => :symbol )
|
239
|
+
end
|
240
|
+
assert_not_nil(row)
|
241
|
+
assert_equal( [[:first, "first"], [:second, "second"], [:third, "third"]],
|
242
|
+
row.to_a )
|
243
|
+
assert_respond_to(row, :unconverted_fields)
|
244
|
+
assert_equal(%w{first second third}, row.unconverted_fields)
|
245
|
+
|
246
|
+
assert_nothing_raised(Exception) do
|
247
|
+
row = FasterCSV.parse_line( data,
|
248
|
+
:converters => :numeric,
|
249
|
+
:unconverted_fields => true,
|
250
|
+
:headers => %w{my new headers},
|
251
|
+
:return_headers => true,
|
252
|
+
:header_converters => :symbol )
|
253
|
+
end
|
254
|
+
assert_not_nil(row)
|
255
|
+
assert_equal( [[:my, "my"], [:new, "new"], [:headers, "headers"]],
|
256
|
+
row.to_a )
|
257
|
+
assert_respond_to(row, :unconverted_fields)
|
258
|
+
assert_equal(Array.new, row.unconverted_fields)
|
259
|
+
end
|
260
|
+
end
|