Permalink
Browse files

Making lineno() CSV aware.

  • Loading branch information...
1 parent 32684fb commit 86701c6082e66a4af73ce15751eaa76a33606bbd bbazzarrakk committed Mar 24, 2006
Showing with 72 additions and 12 deletions.
  1. +3 −0 CHANGELOG
  2. +12 −0 INSTALL
  3. +0 −2 TODO
  4. +17 −6 lib/faster_csv.rb
  5. +15 −0 test/tc_csv_parsing.rb
  6. +6 −4 test/tc_data_converters.rb
  7. +19 −0 test/tc_features.rb
View
@@ -6,6 +6,9 @@ Below is a complete listing of changes for each revision of FasterCSV.
* Added VERSION constant.
* Significantly improved test speed.
+* Worked around Date::parse bug so tests will pass on Windows.
+* Documented test procedure.
+* Made FasterCSV#lineno CSV aware.
== 0.1.9
View
12 INSTALL
@@ -21,3 +21,15 @@ Download the latest version of FasterCSV from the
the root project directory and enter:
$ sudo ruby setup.rb
+
+== Running the Tests
+
+If you would like to run FasterCSV's test suite on your system before installing
+and you have Rake installed, just issue the following command from the root of
+the project directory:
+
+ $ rake
+
+If you do not have rake, use the following command instead:
+
+ $ ruby -I lib:test test/ts_all.rb
View
2 TODO
@@ -28,8 +28,6 @@ order.
"Experiment ID: 3",,,,,,,,,,,,0.92
....
* Add calculated fields.
-* Document test procedure.
-* Fix Date::parse() test errors on Windows.
* It might be nice if "Unclosed Quote Error" dumped you a line number. If it
is possible...
* We've run into a requirement to be able to access the original row of a
View
@@ -544,7 +544,6 @@ def self.generate_line( row, options = Hash.new )
# * fsync()
# * ioctl()
# * isatty()
- # * lineno()
# * pid()
# * pos()
# * reopen()
@@ -704,16 +703,24 @@ def initialize( data, options = Hash.new )
unless options.empty?
raise ArgumentError, "Unknown options: #{options.keys.join(', ')}."
end
+
+ # track our own lineno since IO gets confused about line-ends is CSV fields
+ @lineno = 0
end
+ #
+ # The line number of the last row read from this file. Fields with nested
+ # line-end characters will not affect this count.
+ #
+ attr_reader :lineno
+
### IO and StringIO Delegation ###
extend Forwardable
def_delegators :@io, :binmode, :close, :close_read, :close_write, :closed?,
:eof, :eof?, :fcntl, :fileno, :flush, :fsync, :ioctl,
- :isatty, :lineno, :pid, :pos, :reopen, :rewind, :seek,
- :stat, :string, :sync, :sync=, :tell, :to_i, :to_io,
- :tty?
+ :isatty, :pid, :pos, :reopen, :rewind, :seek, :stat,
+ :string, :sync, :sync=, :tell, :to_i, :to_io, :tty?
### End Delegation ###
@@ -841,7 +848,10 @@ def shift
# I believe a blank line should be an <tt>Array.new</tt>, not
# CSV's <tt>[nil]</tt>
#
- return Array.new if parse.empty?
+ if parse.empty?
+ @lineno += 1
+ return Array.new
+ end
#
# shave leading empty fields if needed, because the main parser chokes
@@ -877,6 +887,7 @@ def shift
# if parse is empty?(), we found all the fields on the line...
if parse.empty?
+ @lineno += 1
# convert fields if needed...
csv = convert_fields(csv) unless header_row? or @converters.empty?
# parse out header rows and handle FasterCSV::Row conversions...
@@ -1048,7 +1059,7 @@ def convert_fields( fields )
field = if converter.arity == 1 # straight field converter
converter[field]
else # FieldInfo converter
- converter[field, FieldInfo.new(index, @io.lineno)]
+ converter[field, FieldInfo.new(index, lineno)]
end
break unless field.is_a? String # short-curcuit pipeline for speed
end
View
@@ -117,5 +117,20 @@ def test_malformed_csv
assert_raise(FasterCSV::MalformedCSVError) do
FasterCSV.parse_line('1,2,"3...')
end
+
+ bad_data = <<-END_DATA.gsub(/^ +/, "")
+ line,1,abc
+ line,2,"def\nghi"
+
+ line,4,8'10"
+ line,5,jkl
+ END_DATA
+ lines = bad_data.to_a
+ assert_equal(6, lines.size)
+ assert_match(/\Aline,4/, lines.find { |l| l =~ /8'10"/ })
+
+# begin
+
+# rescue
end
end
View
@@ -15,6 +15,8 @@ def setup
@parser = FasterCSV.new(@data)
@custom = lambda { |field| field =~ /\A:(\S.*?)\s*\Z/ ? $1.to_sym : field }
+
+ @win_safe_time_str = Time.now.strftime("%a %b %d %H:%M:%S %Y")
end
def test_builtin_integer_converter
@@ -43,7 +45,7 @@ def test_builtin_float_converter
def test_builtin_date_converter
# does convert
- assert_instance_of(Date, FasterCSV::Converters[:date][Time.now.to_s])
+ assert_instance_of(Date, FasterCSV::Converters[:date][@win_safe_time_str])
# does not convert
assert_instance_of(String, FasterCSV::Converters[:date]["junk"])
@@ -52,7 +54,7 @@ def test_builtin_date_converter
def test_builtin_date_time_converter
# does convert
assert_instance_of( DateTime,
- FasterCSV::Converters[:date_time][Time.now.to_s] )
+ FasterCSV::Converters[:date_time][@win_safe_time_str] )
# does not convert
assert_instance_of(String, FasterCSV::Converters[:date_time]["junk"])
@@ -110,8 +112,8 @@ def test_builtin_numeric_combo_converter
def test_builtin_all_nested_combo_converter
# setup parser...
- @data << ",#{Time.now}" # add a DateTime field
- @parser = FasterCSV.new(@data) # reset parser
+ @data << ",#{@win_safe_time_str}" # add a DateTime field
+ @parser = FasterCSV.new(@data) # reset parser
assert_nothing_raised(Exception) { @parser.convert(:all) }
# and use
View
@@ -63,6 +63,25 @@ def test_row_sep_auto_discovery
assert_equal($/, FasterCSV.new(STDERR).instance_eval { @row_sep })
end
+ def test_lineno
+ sample_data = <<-END_DATA.gsub(/^ +/, "")
+ line,1,abc
+ line,2,"def\nghi"
+
+ line,4,jkl
+ END_DATA
+ assert_equal(5, sample_data.to_a.size)
+
+ csv = FasterCSV.new(sample_data)
+ 4.times do |line_count|
+ assert_equal(line_count, csv.lineno)
+ assert_not_nil(csv.shift)
+ assert_equal(line_count + 1, csv.lineno)
+ end
+ assert_nil(csv.shift)
+ csv.close
+ end
+
def test_unknown_options
assert_raise(ArgumentError) do
FasterCSV.new(String.new, :unknown => :error)

0 comments on commit 86701c6

Please sign in to comment.