fastercsv 1.5.1 → 1.5.3
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 +10 -0
- data/lib/faster_csv.rb +24 -15
- data/test/tc_csv_parsing.rb +4 -0
- data/test/tc_interface.rb +1 -1
- data/test/tc_table.rb +2 -0
- metadata +12 -5
data/CHANGELOG
CHANGED
@@ -2,6 +2,16 @@
|
|
2
2
|
|
3
3
|
Below is a complete listing of changes for each revision of FasterCSV.
|
4
4
|
|
5
|
+
== 1.5.3
|
6
|
+
|
7
|
+
* A bug fix from Timothy Elliott to return the new parser to its strict quote
|
8
|
+
tolerance.
|
9
|
+
|
10
|
+
== 1.5.2
|
11
|
+
|
12
|
+
* A bug fix to allow IO Exceptions to reach the calling code from Moses Hohman.
|
13
|
+
* Added support for <tt>:write_headers => false</tt> to Table.to_csv().
|
14
|
+
|
5
15
|
== 1.5.1
|
6
16
|
|
7
17
|
* A bug fix for deleting blank Table rows from Andy Hartford.
|
data/lib/faster_csv.rb
CHANGED
@@ -82,7 +82,7 @@ require "stringio"
|
|
82
82
|
#
|
83
83
|
class FasterCSV
|
84
84
|
# The version of the installed library.
|
85
|
-
VERSION = "1.5.
|
85
|
+
VERSION = "1.5.3".freeze
|
86
86
|
|
87
87
|
#
|
88
88
|
# A FasterCSV::Row is part Array and part Hash. It retains an order for the
|
@@ -704,8 +704,12 @@ class FasterCSV
|
|
704
704
|
# Returns the table as a complete CSV String. Headers will be listed first,
|
705
705
|
# then all of the field rows.
|
706
706
|
#
|
707
|
+
# This method assumes you want the Table.headers(), unless you explicitly
|
708
|
+
# pass <tt>:write_headers => false</tt>.
|
709
|
+
#
|
707
710
|
def to_csv(options = Hash.new)
|
708
|
-
|
711
|
+
wh = options.fetch(:write_headers, true)
|
712
|
+
@table.inject(wh ? [headers.to_csv(options)] : [ ]) do |rows, row|
|
709
713
|
if row.header_row?
|
710
714
|
rows
|
711
715
|
else
|
@@ -1576,10 +1580,10 @@ class FasterCSV
|
|
1576
1580
|
#
|
1577
1581
|
loop do
|
1578
1582
|
# add another read to the line
|
1579
|
-
|
1580
|
-
|
1581
|
-
|
1582
|
-
|
1583
|
+
if read_line = @io.gets(@row_sep)
|
1584
|
+
line += read_line
|
1585
|
+
else
|
1586
|
+
return nil
|
1583
1587
|
end
|
1584
1588
|
# copy the line so we can chop it up in parsing
|
1585
1589
|
parse = line.dup
|
@@ -1610,12 +1614,14 @@ class FasterCSV
|
|
1610
1614
|
parse.split(@col_sep, -1).each do |match|
|
1611
1615
|
if current_field.empty? && match.count(@quote_and_newlines).zero?
|
1612
1616
|
csv << (match.empty? ? nil : match)
|
1613
|
-
elsif(current_field.empty? ? match[0] : current_field[0]) ==
|
1617
|
+
elsif (current_field.empty? ? match[0] : current_field[0]) ==
|
1618
|
+
@quote_char[0]
|
1614
1619
|
current_field << match
|
1615
1620
|
field_quotes += match.count(@quote_char)
|
1616
1621
|
if field_quotes % 2 == 0
|
1617
1622
|
in_quotes = current_field[@parsers[:quoted_field], 1]
|
1618
|
-
raise MalformedCSVError
|
1623
|
+
raise MalformedCSVError if !in_quotes ||
|
1624
|
+
in_quotes[@parsers[:stray_quote]]
|
1619
1625
|
current_field = in_quotes
|
1620
1626
|
current_field.gsub!(@quote_char * 2, @quote_char) # unescape contents
|
1621
1627
|
csv << current_field
|
@@ -1793,14 +1799,17 @@ class FasterCSV
|
|
1793
1799
|
esc_row_sep = Regexp.escape(@row_sep)
|
1794
1800
|
esc_quote = Regexp.escape(@quote_char)
|
1795
1801
|
@parsers = {
|
1796
|
-
:any_field
|
1797
|
-
|
1798
|
-
|
1799
|
-
:quoted_field
|
1800
|
-
|
1801
|
-
|
1802
|
+
:any_field => Regexp.new( "[^#{esc_col_sep}]+",
|
1803
|
+
Regexp::MULTILINE,
|
1804
|
+
@encoding ),
|
1805
|
+
:quoted_field => Regexp.new( "^#{esc_quote}(.*)#{esc_quote}$",
|
1806
|
+
Regexp::MULTILINE,
|
1807
|
+
@encoding ),
|
1808
|
+
:stray_quote => Regexp.new( "[^#{esc_quote}]#{esc_quote}[^#{esc_quote}]",
|
1809
|
+
Regexp::MULTILINE,
|
1810
|
+
@encoding ),
|
1802
1811
|
# safer than chomp!()
|
1803
|
-
:line_end
|
1812
|
+
:line_end => Regexp.new("#{esc_row_sep}\\z", nil, @encoding)
|
1804
1813
|
}
|
1805
1814
|
end
|
1806
1815
|
|
data/test/tc_csv_parsing.rb
CHANGED
@@ -114,6 +114,10 @@ class TestCSVParsing < Test::Unit::TestCase
|
|
114
114
|
[["foo,\"foo,bar,baz,foo\",\"foo\"", ["foo", "foo,bar,baz,foo", "foo"]]].each do |edge_case|
|
115
115
|
assert_equal(edge_case.last, FasterCSV.parse_line(edge_case.first))
|
116
116
|
end
|
117
|
+
|
118
|
+
assert_raise(FasterCSV::MalformedCSVError) do
|
119
|
+
FasterCSV.parse_line("1,\"23\"4\"5\", 6")
|
120
|
+
end
|
117
121
|
end
|
118
122
|
|
119
123
|
def test_malformed_csv
|
data/test/tc_interface.rb
CHANGED
@@ -181,7 +181,7 @@ class TestFasterCSVInterface < Test::Unit::TestCase
|
|
181
181
|
csv << lines.first.keys
|
182
182
|
lines.each { |line| csv << line }
|
183
183
|
end
|
184
|
-
FasterCSV.open( @path, "
|
184
|
+
FasterCSV.open( @path, "r", :headers => true,
|
185
185
|
:converters => :all,
|
186
186
|
:header_converters => :symbol ) do |csv|
|
187
187
|
csv.each { |line| assert_equal(lines.shift, line.to_hash) }
|
data/test/tc_table.rb
CHANGED
@@ -251,6 +251,8 @@ class TestFasterCSVTable < Test::Unit::TestCase
|
|
251
251
|
# with options
|
252
252
|
assert_equal( csv.gsub(",", "|").gsub("\n", "\r\n"),
|
253
253
|
@table.to_csv(:col_sep => "|", :row_sep => "\r\n") )
|
254
|
+
assert_equal( csv.to_a[1..-1].join,
|
255
|
+
@table.to_csv(:write_headers => false) )
|
254
256
|
|
255
257
|
# with headers
|
256
258
|
assert_equal(csv, @header_table.to_csv)
|
metadata
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fastercsv
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 1
|
7
|
+
- 5
|
8
|
+
- 3
|
9
|
+
version: 1.5.3
|
5
10
|
platform: ruby
|
6
11
|
authors:
|
7
12
|
- James Edward Gray II
|
@@ -9,7 +14,7 @@ autorequire:
|
|
9
14
|
bindir: bin
|
10
15
|
cert_chain: []
|
11
16
|
|
12
|
-
date: 2010-
|
17
|
+
date: 2010-03-16 00:00:00 -05:00
|
13
18
|
default_executable:
|
14
19
|
dependencies: []
|
15
20
|
|
@@ -80,18 +85,20 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
80
85
|
requirements:
|
81
86
|
- - ">="
|
82
87
|
- !ruby/object:Gem::Version
|
88
|
+
segments:
|
89
|
+
- 0
|
83
90
|
version: "0"
|
84
|
-
version:
|
85
91
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
86
92
|
requirements:
|
87
93
|
- - ">="
|
88
94
|
- !ruby/object:Gem::Version
|
95
|
+
segments:
|
96
|
+
- 0
|
89
97
|
version: "0"
|
90
|
-
version:
|
91
98
|
requirements: []
|
92
99
|
|
93
100
|
rubyforge_project: fastercsv
|
94
|
-
rubygems_version: 1.3.
|
101
|
+
rubygems_version: 1.3.6
|
95
102
|
signing_key:
|
96
103
|
specification_version: 3
|
97
104
|
summary: FasterCSV is CSV, but faster, smaller, and cleaner.
|