fastercsv 1.0.0 → 1.1.0

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/CHANGELOG CHANGED
@@ -2,6 +2,15 @@
2
2
 
3
3
  Below is a complete listing of changes for each revision of FasterCSV.
4
4
 
5
+ == 1.1.0
6
+
7
+ * Added empty?(), length(), and size() methods to FasterCSV::Row and
8
+ FasterCSV::Table.
9
+ * Cleaned up bug fix regression tests.
10
+ * Fixed bug causing Arrays to be returned for blank rows when header processing
11
+ is active.
12
+ * Added a <tt>:skip_blanks</tt> option for ignoring empty rows.
13
+
5
14
  == 1.0.0
6
15
 
7
16
  * Fixed FasterCSV.rewind() to reset the FasterCSV.lineno() counter.
data/TODO CHANGED
@@ -3,4 +3,4 @@
3
3
  The following is a list of planned expansions for FasterCSV, in no particular
4
4
  order.
5
5
 
6
- * Rent this space!
6
+ * Rent this space...
@@ -0,0 +1,28 @@
1
+ #!/usr/local/bin/ruby -w
2
+
3
+ # csv_converters.rb
4
+ #
5
+ # Created by James Edward Gray II on 2006-11-05.
6
+ # Copyright 2006 Gray Productions. All rights reserved.
7
+
8
+ require "faster_csv"
9
+
10
+ # convert a specific column
11
+ options = {
12
+ :headers => true,
13
+ :header_converters => :symbol,
14
+ :converters => [
15
+ lambda { |f, info| info.index.zero? ? f.to_i : f },
16
+ lambda { |f, info| info.header == :floats ? f.to_f : f }
17
+ ]
18
+ }
19
+ table = FCSV(DATA, options) { |csv| csv.read }
20
+
21
+ table[:ints] # => [1, 2, 3]
22
+ table[:floats] # => [1.0, 2.0, 3.0]
23
+
24
+ __END__
25
+ ints,floats
26
+ 1,1.000
27
+ 2,2
28
+ 3,3.0
data/lib/faster_csv.rb CHANGED
@@ -75,7 +75,7 @@ require "stringio"
75
75
  #
76
76
  class FasterCSV
77
77
  # The version of the installed library.
78
- VERSION = "1.0.0".freeze
78
+ VERSION = "1.1.0".freeze
79
79
 
80
80
  #
81
81
  # A FasterCSV::Row is part Array and part Hash. It retains an order for the
@@ -95,6 +95,13 @@ class FasterCSV
95
95
  # FasterCSV::Row.header_row?() and FasterCSV::Row.field_row?(), that this is
96
96
  # a header row. Otherwise, the row is assumes to be a field row.
97
97
  #
98
+ # A FasterCSV::Row object supports the following Array methods through
99
+ # delegation:
100
+ #
101
+ # * empty?()
102
+ # * length()
103
+ # * size()
104
+ #
98
105
  def initialize(headers, fields, header_row = false)
99
106
  @header_row = header_row
100
107
 
@@ -109,6 +116,11 @@ class FasterCSV
109
116
  # Internal data format used to compare equality.
110
117
  attr_reader :row
111
118
  protected :row
119
+
120
+ ### Array Delegation ###
121
+
122
+ extend Forwardable
123
+ def_delegators :@row, :empty?, :length, :size
112
124
 
113
125
  # Returns +true+ if this is a header row.
114
126
  def header_row?
@@ -367,6 +379,13 @@ class FasterCSV
367
379
  # to be FasterCSV::Row objects. All rows are assumed to have the same
368
380
  # headers.
369
381
  #
382
+ # A FasterCSV::Table object supports the following Array methods through
383
+ # delegation:
384
+ #
385
+ # * empty?()
386
+ # * length()
387
+ # * size()
388
+ #
370
389
  def initialize(array_of_rows)
371
390
  @table = array_of_rows
372
391
  @mode = :col_or_row
@@ -378,6 +397,11 @@ class FasterCSV
378
397
  # Internal data format used to compare equality.
379
398
  attr_reader :table
380
399
  protected :table
400
+
401
+ ### Array Delegation ###
402
+
403
+ extend Forwardable
404
+ def_delegators :@table, :empty?, :length, :size
381
405
 
382
406
  #
383
407
  # Returns a duplicate table object, in column mode. This is handy for
@@ -749,6 +773,7 @@ class FasterCSV
749
773
  # <b><tt>:headers</tt></b>:: +false+
750
774
  # <b><tt>:return_headers</tt></b>:: +false+
751
775
  # <b><tt>:header_converters</tt></b>:: +nil+
776
+ # <b><tt>:skip_blanks</tt></b>:: +false+
752
777
  #
753
778
  DEFAULT_OPTIONS = { :col_sep => ",",
754
779
  :row_sep => :auto,
@@ -756,7 +781,8 @@ class FasterCSV
756
781
  :unconverted_fields => nil,
757
782
  :headers => false,
758
783
  :return_headers => false,
759
- :header_converters => nil }.freeze
784
+ :header_converters => nil,
785
+ :skip_blanks => false }.freeze
760
786
 
761
787
  #
762
788
  # This method will build a drop-in replacement for many of the standard CSV
@@ -1263,6 +1289,9 @@ class FasterCSV
1263
1289
  # <tt>:converters</tt> save that the
1264
1290
  # conversions are only made to header
1265
1291
  # rows.
1292
+ # <b><tt>:skip_blanks</tt></b>:: When set to a +true+ value, FasterCSV
1293
+ # will skip over any rows with no
1294
+ # content.
1266
1295
  #
1267
1296
  # See FasterCSV::DEFAULT_OPTIONS for the default settings.
1268
1297
  #
@@ -1289,14 +1318,14 @@ class FasterCSV
1289
1318
  @lineno = 0
1290
1319
  end
1291
1320
 
1292
- ### IO and StringIO Delegation ###
1293
-
1294
1321
  #
1295
1322
  # The line number of the last row read from this file. Fields with nested
1296
1323
  # line-end characters will not affect this count.
1297
1324
  #
1298
1325
  attr_reader :lineno
1299
1326
 
1327
+ ### IO and StringIO Delegation ###
1328
+
1300
1329
  extend Forwardable
1301
1330
  def_delegators :@io, :binmode, :close, :close_read, :close_write, :closed?,
1302
1331
  :eof, :eof?, :fcntl, :fileno, :flush, :fsync, :ioctl,
@@ -1432,11 +1461,11 @@ class FasterCSV
1432
1461
  # handle headers not based on document content
1433
1462
  if header_row? and @return_headers and
1434
1463
  [Array, String].include? @use_headers.class
1435
- if @unconverted_fields
1436
- return add_unconverted_fields(parse_headers, Array.new)
1437
- else
1438
- return parse_headers
1439
- end
1464
+ if @unconverted_fields
1465
+ return add_unconverted_fields(parse_headers, Array.new)
1466
+ else
1467
+ return parse_headers
1468
+ end
1440
1469
  end
1441
1470
 
1442
1471
  # begin with a blank line, so we can always add to it
@@ -1459,8 +1488,13 @@ class FasterCSV
1459
1488
  #
1460
1489
  if parse.empty?
1461
1490
  @lineno += 1
1462
- if @unconverted_fields
1491
+ if @skip_blanks
1492
+ line = ""
1493
+ next
1494
+ elsif @unconverted_fields
1463
1495
  return add_unconverted_fields(Array.new, Array.new)
1496
+ elsif @use_headers
1497
+ return FasterCSV::Row.new(Array.new, Array.new)
1464
1498
  else
1465
1499
  return Array.new
1466
1500
  end
@@ -1581,6 +1615,9 @@ class FasterCSV
1581
1615
 
1582
1616
  # Pre-compiles parsers and stores them by name for access during reads.
1583
1617
  def init_parsers(options)
1618
+ # store the parser behaviors
1619
+ @skip_blanks = options.delete(:skip_blanks)
1620
+
1584
1621
  # prebuild Regexps for faster parsing
1585
1622
  @parsers = {
1586
1623
  :leading_fields =>
data/test/tc_features.rb CHANGED
@@ -98,23 +98,37 @@ class TestFasterCSVFeatures < Test::Unit::TestCase
98
98
  end
99
99
  end
100
100
 
101
- def test_bug_fixes
102
- # failing to escape <tt>:col_sep</tt> (reported by Kev Jackson)
101
+ def test_skip_blanks
102
+ assert_equal(4, @csv.to_a.size)
103
+
104
+ @csv = FasterCSV.new(@sample_data, :skip_blanks => true)
105
+
106
+ count = 0
107
+ @csv.each do |row|
108
+ count += 1
109
+ assert_equal("line", row.first)
110
+ end
111
+ assert_equal(3, count)
112
+ end
113
+
114
+ # reported by Kev Jackson
115
+ def test_failing_to_escape_col_sep_bug_fix
103
116
  assert_nothing_raised(Exception) do
104
117
  FasterCSV.new(String.new, :col_sep => "|")
105
118
  end
106
-
107
- # failing to reset header behavior on rewind() (reported by Chris Roos)
119
+ end
120
+
121
+ # reported by Chris Roos
122
+ def test_failing_to_reset_headers_in_rewind_bug_fix
108
123
  csv = FasterCSV.new( "forename,surname", :headers => true,
109
124
  :return_headers => true )
110
125
  csv.each { |row| assert row.header_row? }
111
126
  csv.rewind
112
127
  csv.each { |row| assert row.header_row? }
113
-
114
- #
115
- # leading empty fields with multibyte col_sep raises MalformedCSVError
116
- # (reported by Dave Burt)
117
- #
128
+ end
129
+
130
+ # reported by Dave Burt
131
+ def test_leading_empty_fields_with_multibyte_col_sep_bug_fix
118
132
  data = <<-END_DATA.gsub(/^\s+/, "")
119
133
  <=><=>A<=>B<=>C
120
134
  1<=>2<=>3
data/test/tc_headers.rb CHANGED
@@ -224,4 +224,39 @@ class TestFasterCSVHeaders < Test::Unit::TestCase
224
224
 
225
225
  assert_instance_of(FasterCSV::Table, csv)
226
226
  end
227
+
228
+ def test_skip_blanks
229
+ @data = <<-END_CSV.gsub(/^ +/, "")
230
+
231
+
232
+ A,B,C
233
+
234
+ 1,2,3
235
+
236
+
237
+
238
+ END_CSV
239
+
240
+ expected = [%w[1 2 3]]
241
+ FasterCSV.parse(@data, :headers => true, :skip_blanks => true) do |row|
242
+ assert_equal(expected.shift, row.fields)
243
+ end
244
+
245
+ expected = [%w[A B C], %w[1 2 3]]
246
+ FasterCSV.parse( @data,
247
+ :headers => true,
248
+ :return_headers => true,
249
+ :skip_blanks => true ) do |row|
250
+ assert_equal(expected.shift, row.fields)
251
+ end
252
+ end
253
+
254
+ def test_blank_row_bug_fix
255
+ @data += "\n#{@data}" # add a blank row
256
+
257
+ # ensure that everything returned is a Row object
258
+ FasterCSV.parse(@data, :headers => true) do |row|
259
+ assert_instance_of(FasterCSV::Row, row)
260
+ end
261
+ end
227
262
  end
data/test/tc_row.rb CHANGED
@@ -279,4 +279,10 @@ class TestFasterCSVRow < Test::Unit::TestCase
279
279
  assert_equal( "1|2|3|4|\r\n",
280
280
  @row.to_csv(:col_sep => "|", :row_sep => "\r\n") )
281
281
  end
282
+
283
+ def test_array_delegation
284
+ assert(!@row.empty?, "Row was empty.")
285
+
286
+ assert_equal([@row.headers.size, @row.fields.size].max, @row.size)
287
+ end
282
288
  end
data/test/tc_table.rb CHANGED
@@ -382,4 +382,10 @@ class TestFasterCSVTable < Test::Unit::TestCase
382
382
  assert_equal([[1, 3], [4, 6], [7, 9]], @table.by_col.values_at(0, 2))
383
383
  assert_equal(@rows.values_at(0, 2), @table.values_at(0, 2))
384
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
385
391
  end
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.11
3
3
  specification_version: 1
4
4
  name: fastercsv
5
5
  version: !ruby/object:Gem::Version
6
- version: 1.0.0
7
- date: 2006-11-05 00:00:00 -06:00
6
+ version: 1.1.0
7
+ date: 2006-12-12 00:00:00 -06:00
8
8
  summary: FasterCSV is CSV, but faster, smaller, and cleaner.
9
9
  require_paths:
10
10
  - lib
@@ -41,6 +41,7 @@ files:
41
41
  - test/tc_speed.rb
42
42
  - test/tc_table.rb
43
43
  - test/ts_all.rb
44
+ - examples/csv_converters.rb
44
45
  - examples/csv_filter.rb
45
46
  - examples/csv_reading.rb
46
47
  - examples/csv_table.rb