* lib/csv/csv.rb: Reworked CSV's parser and generator to be m17n. Data
is now parsed in the Encoding it is in without need for translation.
* lib/csv/csv.rb: Improved inspect() messages for better IRb support.
* lib/csv/csv.rb: Fixed header writing bug reported by Dov Murik.
* lib/csv/csv.rb: Use custom separators in parsing header Strings as
suggested by Shmulik Regev.
* lib/csv/csv.rb: Added a :write_headers option for outputting headers.
* lib/csv/csv.rb: Handle open() calls in binary mode whenever we can to
workaround a Windows issue where line-ending translation can cause an
off-by-one error in seeking back to a non-zero starting position after
auto-discovery for :row_sep as suggested by Robert Battle.
* lib/csv/csv.rb: Improved the parser to fail faster when fed some forms
of invalid CSV that can be detected without reading ahead.
* lib/csv/csv.rb: Added a :field_size_limit option to control CSV's
lookahead and prevent the parser from biting off more data than
it can chew.
* lib/csv/csv.rb: Added readers for CSV attributes: col_sep(), row_sep(),
quote_char(), field_size_limit(), converters(), unconverted_fields?(),
headers(), return_headers?(), write_headers?(), header_converters(),
skip_blanks?(), and force_quotes?().
* lib/csv/csv.rb: Cleaned up code syntax to be more inline with
Ruby 1.9 than 1.8.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@19441 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-09-20 20:39:03 -04:00
|
|
|
#!/usr/bin/env ruby -w
|
|
|
|
# encoding: UTF-8
|
2007-12-24 21:46:26 -05:00
|
|
|
|
|
|
|
# tc_serialization.rb
|
|
|
|
#
|
|
|
|
# Created by James Edward Gray II on 2005-10-31.
|
|
|
|
# Copyright 2005 James Edward Gray II. You can redistribute or modify this code
|
|
|
|
# under the terms of Ruby's license.
|
|
|
|
|
2010-12-25 01:58:58 -05:00
|
|
|
require_relative "base"
|
2012-07-07 10:14:54 -04:00
|
|
|
require "tempfile"
|
2007-12-24 21:46:26 -05:00
|
|
|
|
|
|
|
# An example of how to provide custom CSV serialization.
|
|
|
|
class Hash
|
|
|
|
def self.csv_load( meta, headers, fields )
|
2007-12-25 00:14:04 -05:00
|
|
|
self[*headers.zip(fields).to_a.flatten.map { |e| eval(e) }]
|
2007-12-24 21:46:26 -05:00
|
|
|
end
|
2009-03-05 22:56:38 -05:00
|
|
|
|
2007-12-24 21:46:26 -05:00
|
|
|
def csv_headers
|
|
|
|
keys.map { |key| key.inspect }
|
|
|
|
end
|
2009-03-05 22:56:38 -05:00
|
|
|
|
2007-12-24 21:46:26 -05:00
|
|
|
def csv_dump( headers )
|
|
|
|
headers.map { |header| fetch(eval(header)).inspect }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2010-12-25 01:58:58 -05:00
|
|
|
class TestCSV::Serialization < TestCSV
|
2010-12-25 21:15:55 -05:00
|
|
|
extend DifferentOFS
|
2009-03-05 22:56:38 -05:00
|
|
|
|
2007-12-24 21:46:26 -05:00
|
|
|
### Classes Used to Test Serialization ###
|
2009-03-05 22:56:38 -05:00
|
|
|
|
2007-12-24 21:46:26 -05:00
|
|
|
class ReadOnlyName
|
|
|
|
def initialize( first, last )
|
|
|
|
@first, @last = first, last
|
|
|
|
end
|
|
|
|
|
|
|
|
attr_reader :first, :last
|
2009-03-05 22:56:38 -05:00
|
|
|
|
2007-12-24 21:46:26 -05:00
|
|
|
def ==( other )
|
|
|
|
%w{first last}.all? { |att| send(att) == other.send(att) }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
Name = Struct.new(:first, :last)
|
2009-03-05 22:56:38 -05:00
|
|
|
|
2007-12-24 21:46:26 -05:00
|
|
|
class FullName < Name
|
|
|
|
def initialize( first, last, suffix = nil )
|
|
|
|
super(first, last)
|
2009-03-05 22:56:38 -05:00
|
|
|
|
2007-12-24 21:46:26 -05:00
|
|
|
@suffix = suffix
|
|
|
|
end
|
2009-03-05 22:56:38 -05:00
|
|
|
|
2007-12-24 21:46:26 -05:00
|
|
|
attr_accessor :suffix
|
2009-03-05 22:56:38 -05:00
|
|
|
|
2007-12-24 21:46:26 -05:00
|
|
|
def ==( other )
|
|
|
|
%w{first last suffix}.all? { |att| send(att) == other.send(att) }
|
|
|
|
end
|
|
|
|
end
|
2009-03-05 22:56:38 -05:00
|
|
|
|
2007-12-24 21:46:26 -05:00
|
|
|
### Tests ###
|
|
|
|
|
|
|
|
def test_class_dump
|
|
|
|
@names = [ %w{James Gray},
|
|
|
|
%w{Dana Gray},
|
|
|
|
%w{Greg Brown} ].map do |first, last|
|
|
|
|
ReadOnlyName.new(first, last)
|
|
|
|
end
|
2009-03-05 22:56:38 -05:00
|
|
|
|
|
|
|
assert_nothing_raised(Exception) do
|
2007-12-24 21:46:26 -05:00
|
|
|
@data = CSV.dump(@names)
|
|
|
|
end
|
|
|
|
assert_equal(<<-END_CLASS_DUMP.gsub(/^\s*/, ""), @data)
|
2010-12-25 01:58:58 -05:00
|
|
|
class,TestCSV::Serialization::ReadOnlyName
|
2007-12-24 21:46:26 -05:00
|
|
|
@first,@last
|
|
|
|
James,Gray
|
|
|
|
Dana,Gray
|
|
|
|
Greg,Brown
|
|
|
|
END_CLASS_DUMP
|
|
|
|
end
|
2009-03-05 22:56:38 -05:00
|
|
|
|
2007-12-24 21:46:26 -05:00
|
|
|
def test_struct_dump
|
|
|
|
@names = [ %w{James Gray},
|
|
|
|
%w{Dana Gray},
|
|
|
|
%w{Greg Brown} ].map do |first, last|
|
|
|
|
Name.new(first, last)
|
|
|
|
end
|
2009-03-05 22:56:38 -05:00
|
|
|
|
|
|
|
assert_nothing_raised(Exception) do
|
2007-12-24 21:46:26 -05:00
|
|
|
@data = CSV.dump(@names)
|
|
|
|
end
|
|
|
|
assert_equal(<<-END_STRUCT_DUMP.gsub(/^\s*/, ""), @data)
|
2010-12-25 01:58:58 -05:00
|
|
|
class,TestCSV::Serialization::Name
|
2007-12-24 21:46:26 -05:00
|
|
|
first=,last=
|
|
|
|
James,Gray
|
|
|
|
Dana,Gray
|
|
|
|
Greg,Brown
|
|
|
|
END_STRUCT_DUMP
|
|
|
|
end
|
2009-03-05 22:56:38 -05:00
|
|
|
|
2007-12-24 21:46:26 -05:00
|
|
|
def test_inherited_struct_dump
|
|
|
|
@names = [ %w{James Gray II},
|
|
|
|
%w{Dana Gray},
|
|
|
|
%w{Greg Brown} ].map do |first, last, suffix|
|
|
|
|
FullName.new(first, last, suffix)
|
|
|
|
end
|
2009-03-05 22:56:38 -05:00
|
|
|
|
|
|
|
assert_nothing_raised(Exception) do
|
2007-12-24 21:46:26 -05:00
|
|
|
@data = CSV.dump(@names)
|
|
|
|
end
|
|
|
|
assert_equal(<<-END_STRUCT_DUMP.gsub(/^\s*/, ""), @data)
|
2010-12-25 01:58:58 -05:00
|
|
|
class,TestCSV::Serialization::FullName
|
2007-12-24 21:46:26 -05:00
|
|
|
@suffix,first=,last=
|
|
|
|
II,James,Gray
|
|
|
|
,Dana,Gray
|
|
|
|
,Greg,Brown
|
|
|
|
END_STRUCT_DUMP
|
|
|
|
end
|
2009-03-05 22:56:38 -05:00
|
|
|
|
2007-12-24 21:46:26 -05:00
|
|
|
def test_load
|
|
|
|
%w{ test_class_dump
|
|
|
|
test_struct_dump
|
|
|
|
test_inherited_struct_dump }.each do |test|
|
|
|
|
send(test)
|
|
|
|
CSV.load(@data).each do |loaded|
|
|
|
|
assert_instance_of(@names.first.class, loaded)
|
|
|
|
assert_equal(@names.shift, loaded)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2009-03-05 22:56:38 -05:00
|
|
|
|
2007-12-24 21:46:26 -05:00
|
|
|
def test_io
|
|
|
|
test_class_dump
|
2009-03-05 22:56:38 -05:00
|
|
|
|
2012-05-08 02:49:59 -04:00
|
|
|
tempfile = Tempfile.new(%w"serialization .csv")
|
|
|
|
tempfile.close
|
|
|
|
data_file = tempfile.path
|
2009-03-30 19:20:44 -04:00
|
|
|
CSV.dump(@names, File.open(data_file, "wb"))
|
2009-03-05 22:56:38 -05:00
|
|
|
|
2007-12-24 21:46:26 -05:00
|
|
|
assert(File.exist?(data_file))
|
|
|
|
assert_equal(<<-END_IO_DUMP.gsub(/^\s*/, ""), File.read(data_file))
|
2010-12-25 01:58:58 -05:00
|
|
|
class,TestCSV::Serialization::ReadOnlyName
|
2007-12-24 21:46:26 -05:00
|
|
|
@first,@last
|
|
|
|
James,Gray
|
|
|
|
Dana,Gray
|
|
|
|
Greg,Brown
|
|
|
|
END_IO_DUMP
|
2009-03-05 22:56:38 -05:00
|
|
|
|
2007-12-24 21:46:26 -05:00
|
|
|
assert_equal(@names, CSV.load(File.open(data_file)))
|
2009-03-05 22:56:38 -05:00
|
|
|
|
2012-05-08 02:49:59 -04:00
|
|
|
tempfile.close(true)
|
2007-12-24 21:46:26 -05:00
|
|
|
end
|
2009-03-05 22:56:38 -05:00
|
|
|
|
2007-12-24 21:46:26 -05:00
|
|
|
def test_custom_dump_and_load
|
2008-10-10 11:09:34 -04:00
|
|
|
obj = {1 => "simple", test: Hash}
|
2007-12-24 21:46:26 -05:00
|
|
|
assert_equal(obj, CSV.load(CSV.dump([obj])).first)
|
|
|
|
end
|
|
|
|
end
|