Merge csv-3.2.5

This commit is contained in:
Hiroshi SHIBATA 2022-08-26 14:54:17 +09:00 committed by nagachika
parent cd0c2a67c4
commit eed5970b64
4 changed files with 99 additions and 54 deletions

View file

@ -1465,6 +1465,46 @@ class CSV
(new(str, **options) << row).string (new(str, **options) << row).string
end end
# :call-seq:
# CSV.generate_lines(rows)
# CSV.generate_lines(rows, **options)
#
# Returns the \String created by generating \CSV from
# using the specified +options+.
#
# Argument +rows+ must be an \Array of row. Row is \Array of \String or \CSV::Row.
#
# Special options:
# * Option <tt>:row_sep</tt> defaults to <tt>"\n"</tt> on Ruby 3.0 or later
# and <tt>$INPUT_RECORD_SEPARATOR</tt> (<tt>$/</tt>) otherwise.:
# $INPUT_RECORD_SEPARATOR # => "\n"
# * This method accepts an additional option, <tt>:encoding</tt>, which sets the base
# Encoding for the output. This method will try to guess your Encoding from
# the first non-+nil+ field in +row+, if possible, but you may need to use
# this parameter as a backup plan.
#
# For other +options+,
# see {Options for Generating}[#class-CSV-label-Options+for+Generating].
#
# ---
#
# Returns the \String generated from an
# CSV.generate_lines(['foo', '0'], ['bar', '1'], ['baz', '2']) # => "foo,0\nbar,1\nbaz.2\n"
#
# ---
#
# Raises an exception
# # Raises NoMethodError (undefined method `find' for :foo:Symbol)
# CSV.generate_lines(:foo)
#
def generate_lines(rows, **options)
self.generate(**options) do |csv|
rows.each do |row|
csv << row
end
end
end
# #
# :call-seq: # :call-seq:
# open(file_path, mode = "rb", **options ) -> new_csv # open(file_path, mode = "rb", **options ) -> new_csv

View file

@ -2,5 +2,5 @@
class CSV class CSV
# The version of the installed library. # The version of the installed library.
VERSION = "3.2.4" VERSION = "3.2.5"
end end

View file

@ -85,6 +85,15 @@ testrow
LINE LINE
end end
def test_generate_lines
lines = CSV.generate_lines([["foo", "bar"], [1, 2], [3, 4]])
assert_equal(<<-LINES, lines)
foo,bar
1,2
3,4
LINES
end
def test_headers_detection def test_headers_detection
headers = ["a", "b", "c"] headers = ["a", "b", "c"]
CSV.open(@output.path, "w", headers: true) do |csv| CSV.open(@output.path, "w", headers: true) do |csv|

View file

@ -15,6 +15,22 @@ class TestCSVParseConvert < Test::Unit::TestCase
@time = Time.utc(2018, 12, 30, 6, 41, 29) @time = Time.utc(2018, 12, 30, 6, 41, 29)
@windows_safe_time_data = @time.strftime("%a %b %d %H:%M:%S %Y") @windows_safe_time_data = @time.strftime("%a %b %d %H:%M:%S %Y")
@preserving_converter = lambda do |field, info|
f = field.encode(CSV::ConverterEncoding)
return f if info.quoted?
begin
Integer(f, 10)
rescue
f
end
end
@quoted_header_converter = lambda do |field, info|
f = field.encode(CSV::ConverterEncoding)
return f if info.quoted?
f.to_sym
end
end end
def test_integer def test_integer
@ -108,31 +124,12 @@ class TestCSVParseConvert < Test::Unit::TestCase
CSV.parse_line(',"",a', empty_value: "empty")) CSV.parse_line(',"",a', empty_value: "empty"))
end end
sub_test_case("#quoted?") do def test_quoted_parse_line
def setup
@preserving_converter = lambda do |field, info|
f = field.encode(CSV::ConverterEncoding)
return f if info.quoted?
begin
Integer(f, 10)
rescue
f
end
end
@quoted_header_converter = lambda do |field, info|
f = field.encode(CSV::ConverterEncoding)
return f if info.quoted?
f.to_sym
end
end
def test_parse_line
row = CSV.parse_line('1,"2",3', converters: @preserving_converter) row = CSV.parse_line('1,"2",3', converters: @preserving_converter)
assert_equal([1, "2", 3], row) assert_equal([1, "2", 3], row)
end end
def test_parse def test_quoted_parse
expected = [["quoted", "unquoted"], ["109", 1], ["10A", 2]] expected = [["quoted", "unquoted"], ["109", 1], ["10A", 2]]
rows = CSV.parse(<<~CSV, converters: @preserving_converter) rows = CSV.parse(<<~CSV, converters: @preserving_converter)
"quoted",unquoted "quoted",unquoted
@ -142,12 +139,12 @@ class TestCSVParseConvert < Test::Unit::TestCase
assert_equal(expected, rows) assert_equal(expected, rows)
end end
def test_alternating_quote def test_quoted_alternating_quote
row = CSV.parse_line('"1",2,"3"', converters: @preserving_converter) row = CSV.parse_line('"1",2,"3"', converters: @preserving_converter)
assert_equal(['1', 2, '3'], row) assert_equal(['1', 2, '3'], row)
end end
def test_parse_headers def test_quoted_parse_headers
expected = [["quoted", :unquoted], ["109", "1"], ["10A", "2"]] expected = [["quoted", :unquoted], ["109", "1"], ["10A", "2"]]
table = CSV.parse(<<~CSV, headers: true, header_converters: @quoted_header_converter) table = CSV.parse(<<~CSV, headers: true, header_converters: @quoted_header_converter)
"quoted",unquoted "quoted",unquoted
@ -157,7 +154,7 @@ class TestCSVParseConvert < Test::Unit::TestCase
assert_equal(expected, table.to_a) assert_equal(expected, table.to_a)
end end
def test_parse_with_string_headers def test_quoted_parse_with_string_headers
expected = [["quoted", :unquoted], %w[109 1], %w[10A 2]] expected = [["quoted", :unquoted], %w[109 1], %w[10A 2]]
table = CSV.parse(<<~CSV, headers: '"quoted",unquoted', header_converters: @quoted_header_converter) table = CSV.parse(<<~CSV, headers: '"quoted",unquoted', header_converters: @quoted_header_converter)
"109",1 "109",1
@ -165,5 +162,4 @@ class TestCSVParseConvert < Test::Unit::TestCase
CSV CSV
assert_equal(expected, table.to_a) assert_equal(expected, table.to_a)
end end
end
end end