rw_fastercsv 1.5.6
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/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
|