b2b2dot0-fastercsv 1.4.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.
@@ -0,0 +1,154 @@
1
+ #!/usr/local/bin/ruby -w
2
+
3
+ # tc_serialization.rb
4
+ #
5
+ # Created by James Edward Gray II on 2006-03-28.
6
+ # Copyright 2006 Gray Productions. All rights reserved.
7
+
8
+ require "test/unit"
9
+
10
+ require "faster_csv"
11
+
12
+ # An example of how to provide custom CSV serialization.
13
+ class Hash
14
+ def self.csv_load( meta, headers, fields )
15
+ self[*headers.zip(fields).flatten.map { |e| eval(e) }]
16
+ end
17
+
18
+ def csv_headers
19
+ keys.map { |key| key.inspect }
20
+ end
21
+
22
+ def csv_dump( headers )
23
+ headers.map { |header| fetch(eval(header)).inspect }
24
+ end
25
+ end
26
+
27
+ class TestSerialization < Test::Unit::TestCase
28
+
29
+ ### Classes Used to Test Serialization ###
30
+
31
+ class ReadOnlyName
32
+ def initialize( first, last )
33
+ @first, @last = first, last
34
+ end
35
+
36
+ attr_reader :first, :last
37
+
38
+ def ==( other )
39
+ %w{first last}.all? { |att| send(att) == other.send(att) }
40
+ end
41
+ end
42
+
43
+ Name = Struct.new(:first, :last)
44
+
45
+ class FullName < Name
46
+ def initialize( first, last, suffix = nil )
47
+ super(first, last)
48
+
49
+ @suffix = suffix
50
+ end
51
+
52
+ attr_accessor :suffix
53
+
54
+ def ==( other )
55
+ %w{first last suffix}.all? { |att| send(att) == other.send(att) }
56
+ end
57
+ end
58
+
59
+ ### Tests ###
60
+
61
+ def test_class_dump
62
+ @names = [ %w{James Gray},
63
+ %w{Dana Gray},
64
+ %w{Greg Brown} ].map do |first, last|
65
+ ReadOnlyName.new(first, last)
66
+ end
67
+
68
+ assert_nothing_raised(Exception) do
69
+ @data = FasterCSV.dump(@names)
70
+ end
71
+ assert_equal(<<-END_CLASS_DUMP.gsub(/^\s*/, ""), @data)
72
+ class,TestSerialization::ReadOnlyName
73
+ @first,@last
74
+ James,Gray
75
+ Dana,Gray
76
+ Greg,Brown
77
+ END_CLASS_DUMP
78
+ end
79
+
80
+ def test_struct_dump
81
+ @names = [ %w{James Gray},
82
+ %w{Dana Gray},
83
+ %w{Greg Brown} ].map do |first, last|
84
+ Name.new(first, last)
85
+ end
86
+
87
+ assert_nothing_raised(Exception) do
88
+ @data = FasterCSV.dump(@names)
89
+ end
90
+ assert_equal(<<-END_STRUCT_DUMP.gsub(/^\s*/, ""), @data)
91
+ class,TestSerialization::Name
92
+ first=,last=
93
+ James,Gray
94
+ Dana,Gray
95
+ Greg,Brown
96
+ END_STRUCT_DUMP
97
+ end
98
+
99
+ def test_inherited_struct_dump
100
+ @names = [ %w{James Gray II},
101
+ %w{Dana Gray},
102
+ %w{Greg Brown} ].map do |first, last, suffix|
103
+ FullName.new(first, last, suffix)
104
+ end
105
+
106
+ assert_nothing_raised(Exception) do
107
+ @data = FasterCSV.dump(@names)
108
+ end
109
+ assert_equal(<<-END_STRUCT_DUMP.gsub(/^\s*/, ""), @data)
110
+ class,TestSerialization::FullName
111
+ @suffix,first=,last=
112
+ II,James,Gray
113
+ ,Dana,Gray
114
+ ,Greg,Brown
115
+ END_STRUCT_DUMP
116
+ end
117
+
118
+ def test_load
119
+ %w{ test_class_dump
120
+ test_struct_dump
121
+ test_inherited_struct_dump }.each do |test|
122
+ send(test)
123
+ FasterCSV.load(@data).each do |loaded|
124
+ assert_instance_of(@names.first.class, loaded)
125
+ assert_equal(@names.shift, loaded)
126
+ end
127
+ end
128
+ end
129
+
130
+ def test_io
131
+ test_class_dump
132
+
133
+ data_file = File.join(File.dirname(__FILE__), "temp_test_data.csv")
134
+ FasterCSV.dump(@names, File.open(data_file, "w"))
135
+
136
+ assert(File.exist?(data_file))
137
+ assert_equal(<<-END_IO_DUMP.gsub(/^\s*/, ""), File.read(data_file))
138
+ class,TestSerialization::ReadOnlyName
139
+ @first,@last
140
+ James,Gray
141
+ Dana,Gray
142
+ Greg,Brown
143
+ END_IO_DUMP
144
+
145
+ assert_equal(@names, FasterCSV.load(File.open(data_file)))
146
+
147
+ File.unlink(data_file)
148
+ end
149
+
150
+ def test_custom_dump_and_load
151
+ obj = {1 => "simple", :test => Hash}
152
+ assert_equal(obj, FasterCSV.load(FasterCSV.dump([obj])).first)
153
+ end
154
+ end
@@ -0,0 +1,65 @@
1
+ #!/usr/local/bin/ruby -w
2
+
3
+ # tc_speed.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
+ require "timeout"
10
+
11
+ require "faster_csv"
12
+ require "csv"
13
+
14
+ class TestFasterCSVSpeed < Test::Unit::TestCase
15
+ PATH = File.join(File.dirname(__FILE__), "test_data.csv")
16
+ BIG_DATA = "123456789\n" * 1024
17
+
18
+ def test_that_we_are_doing_the_same_work
19
+ FasterCSV.open(PATH) do |csv|
20
+ CSV.foreach(PATH) do |row|
21
+ assert_equal(row, csv.shift)
22
+ end
23
+ end
24
+ end
25
+
26
+ def test_speed_vs_csv
27
+ csv_time = Time.now
28
+ CSV.foreach(PATH) do |row|
29
+ # do nothing, we're just timing a read...
30
+ end
31
+ csv_time = Time.now - csv_time
32
+
33
+ faster_csv_time = Time.now
34
+ FasterCSV.foreach(PATH) do |row|
35
+ # do nothing, we're just timing a read...
36
+ end
37
+ faster_csv_time = Time.now - faster_csv_time
38
+
39
+ assert(faster_csv_time < csv_time / 3)
40
+ end
41
+
42
+ def test_the_parse_fails_fast_when_it_can_for_unquoted_fields
43
+ assert_parse_errors_out('valid,fields,bad start"' + BIG_DATA)
44
+ end
45
+
46
+ def test_the_parse_fails_fast_when_it_can_for_unescaped_quotes
47
+ assert_parse_errors_out('valid,fields,"bad start"unescaped' + BIG_DATA)
48
+ end
49
+
50
+ def test_field_size_limit_controls_lookahead
51
+ assert_parse_errors_out( 'valid,fields,"' + BIG_DATA + '"',
52
+ :field_size_limit => 2048 )
53
+ end
54
+
55
+ private
56
+
57
+ def assert_parse_errors_out(*args)
58
+ assert_raise(FasterCSV::MalformedCSVError) do
59
+ Timeout.timeout(0.2) do
60
+ FasterCSV.parse(*args)
61
+ fail("Parse didn't error out")
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,400 @@
1
+ #!/usr/local/bin/ruby -w
2
+
3
+ # tc_table.rb
4
+ #
5
+ # Created by James Edward Gray II on 2006-02-24.
6
+ # Copyright 2006 Gray Productions. All rights reserved.
7
+
8
+ require "test/unit"
9
+
10
+ require "faster_csv"
11
+
12
+ class TestFasterCSVTable < Test::Unit::TestCase
13
+ def setup
14
+ @rows = [ FasterCSV::Row.new(%w{A B C}, [1, 2, 3]),
15
+ FasterCSV::Row.new(%w{A B C}, [4, 5, 6]),
16
+ FasterCSV::Row.new(%w{A B C}, [7, 8, 9]) ]
17
+ @table = FasterCSV::Table.new(@rows)
18
+
19
+ @header_table = FasterCSV::Table.new(
20
+ [FasterCSV::Row.new(%w{A B C}, %w{A B C}, true)] + @rows
21
+ )
22
+ end
23
+
24
+ def test_initialze
25
+ assert_not_nil(@table)
26
+ assert_instance_of(FasterCSV::Table, @table)
27
+ end
28
+
29
+ def test_modes
30
+ assert_equal(:col_or_row, @table.mode)
31
+
32
+ # non-destructive changes, intended for one shot calls
33
+ cols = @table.by_col
34
+ assert_equal(:col_or_row, @table.mode)
35
+ assert_equal(:col, cols.mode)
36
+ assert_equal(@table, cols)
37
+
38
+ rows = @table.by_row
39
+ assert_equal(:col_or_row, @table.mode)
40
+ assert_equal(:row, rows.mode)
41
+ assert_equal(@table, rows)
42
+
43
+ # destructive mode changing calls
44
+ assert_equal(@table, @table.by_row!)
45
+ assert_equal(:row, @table.mode)
46
+ assert_equal(@table, @table.by_col_or_row!)
47
+ assert_equal(:col_or_row, @table.mode)
48
+ end
49
+
50
+ def test_headers
51
+ assert_equal(@rows.first.headers, @table.headers)
52
+ end
53
+
54
+ def test_index
55
+ ##################
56
+ ### Mixed Mode ###
57
+ ##################
58
+ # by row
59
+ @rows.each_index { |i| assert_equal(@rows[i], @table[i]) }
60
+ assert_equal(nil, @table[100]) # empty row
61
+
62
+ # by col
63
+ @rows.first.headers.each do |header|
64
+ assert_equal(@rows.map { |row| row[header] }, @table[header])
65
+ end
66
+ assert_equal([nil] * @rows.size, @table["Z"]) # empty col
67
+
68
+ # by cell, row then col
69
+ assert_equal(2, @table[0][1])
70
+ assert_equal(6, @table[1]["C"])
71
+
72
+ # by cell, col then row
73
+ assert_equal(5, @table["B"][1])
74
+ assert_equal(9, @table["C"][2])
75
+
76
+ # with headers (by col)
77
+ assert_equal(["B", 2, 5, 8], @header_table["B"])
78
+
79
+ ###################
80
+ ### Column Mode ###
81
+ ###################
82
+ @table.by_col!
83
+
84
+ assert_equal([2, 5, 8], @table[1])
85
+ assert_equal([2, 5, 8], @table["B"])
86
+
87
+ ################
88
+ ### Row Mode ###
89
+ ################
90
+ @table.by_row!
91
+
92
+ assert_equal(@rows[1], @table[1])
93
+ assert_raise(TypeError) { @table["B"] }
94
+
95
+ ############################
96
+ ### One Shot Mode Change ###
97
+ ############################
98
+ assert_equal(@rows[1], @table[1])
99
+ assert_equal([2, 5, 8], @table.by_col[1])
100
+ assert_equal(@rows[1], @table[1])
101
+ end
102
+
103
+ def test_set_row_or_column
104
+ ##################
105
+ ### Mixed Mode ###
106
+ ##################
107
+ # set row
108
+ @table[2] = [10, 11, 12]
109
+ assert_equal([%w[A B C], [1, 2, 3], [4, 5, 6], [10, 11, 12]], @table.to_a)
110
+
111
+ @table[3] = FasterCSV::Row.new(%w[A B C], [13, 14, 15])
112
+ assert_equal( [%w[A B C], [1, 2, 3], [4, 5, 6], [10, 11, 12], [13, 14, 15]],
113
+ @table.to_a )
114
+
115
+ # set col
116
+ @table["Type"] = "data"
117
+ assert_equal( [ %w[A B C Type],
118
+ [1, 2, 3, "data"],
119
+ [4, 5, 6, "data"],
120
+ [10, 11, 12, "data"],
121
+ [13, 14, 15, "data"] ],
122
+ @table.to_a )
123
+
124
+ @table["Index"] = [1, 2, 3]
125
+ assert_equal( [ %w[A B C Type Index],
126
+ [1, 2, 3, "data", 1],
127
+ [4, 5, 6, "data", 2],
128
+ [10, 11, 12, "data", 3],
129
+ [13, 14, 15, "data", nil] ],
130
+ @table.to_a )
131
+
132
+ @table["B"] = [100, 200]
133
+ assert_equal( [ %w[A B C Type Index],
134
+ [1, 100, 3, "data", 1],
135
+ [4, 200, 6, "data", 2],
136
+ [10, nil, 12, "data", 3],
137
+ [13, nil, 15, "data", nil] ],
138
+ @table.to_a )
139
+
140
+ # verify resulting table
141
+ assert_equal(<<-END_RESULT.gsub(/^\s+/, ""), @table.to_csv)
142
+ A,B,C,Type,Index
143
+ 1,100,3,data,1
144
+ 4,200,6,data,2
145
+ 10,,12,data,3
146
+ 13,,15,data,
147
+ END_RESULT
148
+
149
+ # with headers
150
+ @header_table["Type"] = "data"
151
+ assert_equal(%w[Type data data data], @header_table["Type"])
152
+
153
+ ###################
154
+ ### Column Mode ###
155
+ ###################
156
+ @table.by_col!
157
+
158
+ @table[1] = [2, 5, 11, 14]
159
+ assert_equal( [ %w[A B C Type Index],
160
+ [1, 2, 3, "data", 1],
161
+ [4, 5, 6, "data", 2],
162
+ [10, 11, 12, "data", 3],
163
+ [13, 14, 15, "data", nil] ],
164
+ @table.to_a )
165
+
166
+ @table["Extra"] = "new stuff"
167
+ assert_equal( [ %w[A B C Type Index Extra],
168
+ [1, 2, 3, "data", 1, "new stuff"],
169
+ [4, 5, 6, "data", 2, "new stuff"],
170
+ [10, 11, 12, "data", 3, "new stuff"],
171
+ [13, 14, 15, "data", nil, "new stuff"] ],
172
+ @table.to_a )
173
+
174
+ ################
175
+ ### Row Mode ###
176
+ ################
177
+ @table.by_row!
178
+
179
+ @table[1] = (1..6).to_a
180
+ assert_equal( [ %w[A B C Type Index Extra],
181
+ [1, 2, 3, "data", 1, "new stuff"],
182
+ [1, 2, 3, 4, 5, 6],
183
+ [10, 11, 12, "data", 3, "new stuff"],
184
+ [13, 14, 15, "data", nil, "new stuff"] ],
185
+ @table.to_a )
186
+
187
+ assert_raise(TypeError) { @table["Extra"] = nil }
188
+ end
189
+
190
+ def test_each
191
+ ######################
192
+ ### Mixed/Row Mode ###
193
+ ######################
194
+ i = 0
195
+ @table.each do |row|
196
+ assert_equal(@rows[i], row)
197
+ i += 1
198
+ end
199
+
200
+ # verify that we can chain the call
201
+ assert_equal(@table, @table.each { })
202
+
203
+ ###################
204
+ ### Column Mode ###
205
+ ###################
206
+ @table.by_col!
207
+
208
+ headers = @table.headers
209
+ @table.each do |header, column|
210
+ assert_equal(headers.shift, header)
211
+ assert_equal(@table[header], column)
212
+ end
213
+
214
+ ############################
215
+ ### One Shot Mode Change ###
216
+ ############################
217
+ @table.by_col_or_row!
218
+
219
+ @table.each { |row| assert_instance_of(FasterCSV::Row, row) }
220
+ @table.by_col.each { |tuple| assert_instance_of(Array, tuple) }
221
+ @table.each { |row| assert_instance_of(FasterCSV::Row, row) }
222
+ end
223
+
224
+ def test_enumerable
225
+ assert_equal( @rows.values_at(0, 2),
226
+ @table.select { |row| (row["B"] % 2).zero? } )
227
+
228
+ assert_equal(@rows[1], @table.find { |row| row["C"] > 5 })
229
+ end
230
+
231
+ def test_to_a
232
+ assert_equal([%w[A B C], [1, 2, 3], [4, 5, 6], [7, 8, 9]], @table.to_a)
233
+
234
+ # with headers
235
+ assert_equal( [%w[A B C], [1, 2, 3], [4, 5, 6], [7, 8, 9]],
236
+ @header_table.to_a )
237
+ end
238
+
239
+ def test_to_csv
240
+ csv = <<-END_CSV.gsub(/^\s+/, "")
241
+ A,B,C
242
+ 1,2,3
243
+ 4,5,6
244
+ 7,8,9
245
+ END_CSV
246
+
247
+ # normal conversion
248
+ assert_equal(csv, @table.to_csv)
249
+ assert_equal(csv, @table.to_s) # alias
250
+
251
+ # with options
252
+ assert_equal( csv.gsub(",", "|").gsub("\n", "\r\n"),
253
+ @table.to_csv(:col_sep => "|", :row_sep => "\r\n") )
254
+
255
+ # with headers
256
+ assert_equal(csv, @header_table.to_csv)
257
+ end
258
+
259
+ def test_append
260
+ # verify that we can chain the call
261
+ assert_equal(@table, @table << [10, 11, 12])
262
+
263
+ # Array append
264
+ assert_equal(FasterCSV::Row.new(%w[A B C], [10, 11, 12]), @table[-1])
265
+
266
+ # Row append
267
+ assert_equal(@table, @table << FasterCSV::Row.new(%w[A B C], [13, 14, 15]))
268
+ assert_equal(FasterCSV::Row.new(%w[A B C], [13, 14, 15]), @table[-1])
269
+ end
270
+
271
+ def test_delete
272
+ ##################
273
+ ### Mixed Mode ###
274
+ ##################
275
+ # delete a row
276
+ assert_equal(@rows[1], @table.delete(1))
277
+
278
+ # delete a col
279
+ assert_equal(@rows.map { |row| row["A"] }, @table.delete("A"))
280
+
281
+ # verify resulting table
282
+ assert_equal(<<-END_RESULT.gsub(/^\s+/, ""), @table.to_csv)
283
+ B,C
284
+ 2,3
285
+ 8,9
286
+ END_RESULT
287
+
288
+ ###################
289
+ ### Column Mode ###
290
+ ###################
291
+ setup
292
+ @table.by_col!
293
+
294
+ assert_equal(@rows.map { |row| row[0] }, @table.delete(0))
295
+ assert_equal(@rows.map { |row| row["C"] }, @table.delete("C"))
296
+
297
+ # verify resulting table
298
+ assert_equal(<<-END_RESULT.gsub(/^\s+/, ""), @table.to_csv)
299
+ B
300
+ 2
301
+ 5
302
+ 8
303
+ END_RESULT
304
+
305
+ ################
306
+ ### Row Mode ###
307
+ ################
308
+ setup
309
+ @table.by_row!
310
+
311
+ assert_equal(@rows[1], @table.delete(1))
312
+ assert_raise(TypeError) { @table.delete("C") }
313
+
314
+ # verify resulting table
315
+ assert_equal(<<-END_RESULT.gsub(/^\s+/, ""), @table.to_csv)
316
+ A,B,C
317
+ 1,2,3
318
+ 7,8,9
319
+ END_RESULT
320
+ end
321
+
322
+ def test_delete_if
323
+ ######################
324
+ ### Mixed/Row Mode ###
325
+ ######################
326
+ # verify that we can chain the call
327
+ assert_equal(@table, @table.delete_if { |row| (row["B"] % 2).zero? })
328
+
329
+ # verify resulting table
330
+ assert_equal(<<-END_RESULT.gsub(/^\s+/, ""), @table.to_csv)
331
+ A,B,C
332
+ 4,5,6
333
+ END_RESULT
334
+
335
+ ###################
336
+ ### Column Mode ###
337
+ ###################
338
+ setup
339
+ @table.by_col!
340
+
341
+ assert_equal(@table, @table.delete_if { |h, v| h > "A" })
342
+ assert_equal(<<-END_RESULT.gsub(/^\s+/, ""), @table.to_csv)
343
+ A
344
+ 1
345
+ 4
346
+ 7
347
+ END_RESULT
348
+ end
349
+
350
+ def test_values_at
351
+ ##################
352
+ ### Mixed Mode ###
353
+ ##################
354
+ # rows
355
+ assert_equal(@rows.values_at(0, 2), @table.values_at(0, 2))
356
+ assert_equal(@rows.values_at(1..2), @table.values_at(1..2))
357
+
358
+ # cols
359
+ assert_equal([[1, 3], [4, 6], [7, 9]], @table.values_at("A", "C"))
360
+ assert_equal([[2, 3], [5, 6], [8, 9]], @table.values_at("B".."C"))
361
+
362
+ ###################
363
+ ### Column Mode ###
364
+ ###################
365
+ @table.by_col!
366
+
367
+ assert_equal([[1, 3], [4, 6], [7, 9]], @table.values_at(0, 2))
368
+ assert_equal([[1, 3], [4, 6], [7, 9]], @table.values_at("A", "C"))
369
+
370
+ ################
371
+ ### Row Mode ###
372
+ ################
373
+ @table.by_row!
374
+
375
+ assert_equal(@rows.values_at(0, 2), @table.values_at(0, 2))
376
+ assert_raise(TypeError) { @table.values_at("A", "C") }
377
+
378
+ ############################
379
+ ### One Shot Mode Change ###
380
+ ############################
381
+ assert_equal(@rows.values_at(0, 2), @table.values_at(0, 2))
382
+ assert_equal([[1, 3], [4, 6], [7, 9]], @table.by_col.values_at(0, 2))
383
+ assert_equal(@rows.values_at(0, 2), @table.values_at(0, 2))
384
+ end
385
+
386
+ def test_array_delegation
387
+ assert(!@table.empty?, "Table was empty.")
388
+
389
+ assert_equal(@rows.size, @table.size)
390
+ end
391
+
392
+ def test_inspect_shows_current_mode
393
+ str = @table.inspect
394
+ assert(str.include?("mode:#{@table.mode}"), "Mode not shown.")
395
+
396
+ @table.by_col!
397
+ str = @table.inspect
398
+ assert(str.include?("mode:#{@table.mode}"), "Mode not shown.")
399
+ end
400
+ end