From 3c3e659196b7511f02b03e2904c40a29993a184c Mon Sep 17 00:00:00 2001 From: jeg2 Date: Mon, 20 Aug 2012 20:52:36 +0000 Subject: * lib/csv.rb: Fixes #161 on github * lib/csv.rb: You can now specify a pattern for :skip_lines. Matching lines will not be passed to the CSV parser. * lib/csv.rb: Patch by Christian Schwartz. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@36743 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 11 +++++++++-- lib/csv.rb | 25 ++++++++++++++++++++++++- test/csv/test_features.rb | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index adbe9e6593..bde75d9e7a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,14 @@ +Tue Aug 21 05:43:00 2012 James Edward Gray II + + * lib/csv.rb: Fixes #161 on github + * lib/csv.rb: You can now specify a pattern for :skip_lines. + Matching lines will not be passed to the CSV parser. + * lib/csv.rb: Patch by Christian Schwartz. + Tue Aug 21 05:25:41 2012 Eric Hodel - * re.c (rb_reg_initialize_m): Forgot to update output for or'd-options - example. + * re.c (rb_reg_initialize_m): Forgot to update output for or'd-options + example. Tue Aug 21 05:18:03 2012 Eric Hodel diff --git a/lib/csv.rb b/lib/csv.rb index 13f86ec318..45da2c9bd6 100644 --- a/lib/csv.rb +++ b/lib/csv.rb @@ -973,6 +973,7 @@ class CSV # :header_converters:: +nil+ # :skip_blanks:: +false+ # :force_quotes:: +false+ + # :skip_lines:: +nil+ # DEFAULT_OPTIONS = { col_sep: ",", row_sep: :auto, @@ -984,7 +985,8 @@ class CSV return_headers: false, header_converters: nil, skip_blanks: false, - force_quotes: false }.freeze + force_quotes: false, + skip_lines: nil }.freeze # # This method will return a CSV instance, just like CSV::new(), but the @@ -1554,6 +1556,14 @@ class CSV # skip over any rows with no content. # :force_quotes:: When set to a +true+ value, CSV will # quote all CSV fields it creates. + # :skip_lines:: When set to an object responding to + # match, every line matching + # it is considered a comment and ignored + # during parsing. When set to +nil+ + # no line is considered a comment. + # If the passed object does not respond + # to match, ArgumentError + # is thrown. # # See CSV::DEFAULT_OPTIONS for the default settings. # @@ -1591,6 +1601,7 @@ class CSV init_parsers(options) init_converters(options) init_headers(options) + init_comments(options) options.delete(:encoding) options.delete(:internal_encoding) @@ -1620,6 +1631,10 @@ class CSV attr_reader :quote_char # The limit for field size, if any. See CSV::new for details. attr_reader :field_size_limit + + # The regex marking a line as a comment. See CSV::new for details + attr_reader :skip_lines + # # Returns the current list of converters in effect. See CSV::new for details. # Built-in converters will be returned by name, while others will be returned @@ -1873,6 +1888,8 @@ class CSV end end + next if @skip_lines and @skip_lines.match parse + parts = parse.split(@col_sep, -1) if parts.empty? if in_extended_col @@ -2189,6 +2206,12 @@ class CSV init_converters(options, :header_converters) end + def init_comments(options) + @skip_lines = options.delete(:skip_lines) + if @skip_lines and not @skip_lines.respond_to?(:match) + raise ArgumentError, ":skip_lines has to respond to matches" + end + end # # The actual work method for adding converters, used by both CSV.convert() and # CSV.header_convert(). diff --git a/test/csv/test_features.rb b/test/csv/test_features.rb index 7176cca0e0..ded876abbe 100755 --- a/test/csv/test_features.rb +++ b/test/csv/test_features.rb @@ -274,4 +274,37 @@ class TestCSV::Features < TestCSV assert(CSV::VERSION.frozen?) assert_match(/\A\d\.\d\.\d\Z/, CSV::VERSION) end + + def test_accepts_comment_skip_lines_option + assert_nothing_raised(ArgumentError) do + CSV.new nil, :skip_lines => /\A\s*#/ + end + end + + def test_accepts_comment_defaults_to_nil + c = CSV.new nil + assert_equal c.skip_lines, nil + end + + class RegexStub + end + + def test_requires_skip_lines_to_call_match + regex_stub = RegexStub.new + assert_raise(ArgumentError) do + CSV.new nil, :skip_lines => regex_stub + end + end + + def test_comment_rows_are_ignored + sample_data = "line,1,a\n#not,a,line\nline,2,b\n #also,no,line" + c = CSV.new sample_data, :skip_lines => /\A\s*#/ + assert_equal c.each.to_a, [["line", "1", "a"], ["line", "2", "b"]] + end + + def test_quoted_skip_line_markers_are_ignored + sample_data = "line,1,a\n\"#not\",a,line\nline,2,b" + c = CSV.new sample_data, :skip_lines => /\A\s*#/ + assert_equal c.each.to_a, [["line", "1", "a"], ["#not", "a", "line"], ["line", "2", "b"]] + end end -- cgit v1.2.3