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 +9 -0
- data/TODO +1 -1
- data/examples/csv_converters.rb +28 -0
- data/lib/faster_csv.rb +47 -10
- data/test/tc_features.rb +23 -9
- data/test/tc_headers.rb +35 -0
- data/test/tc_row.rb +6 -0
- data/test/tc_table.rb +6 -0
- metadata +3 -2
    
        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
    
    
| @@ -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. | 
| 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 | 
| 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 | 
            -
             | 
| 1436 | 
            -
             | 
| 1437 | 
            -
             | 
| 1438 | 
            -
             | 
| 1439 | 
            -
             | 
| 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 @ | 
| 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  | 
| 102 | 
            -
                 | 
| 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 | 
            -
             | 
| 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 | 
            -
             | 
| 116 | 
            -
             | 
| 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. | 
| 7 | 
            -
            date: 2006- | 
| 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
         |