csv 3.2.0 → 3.2.1
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.
- checksums.yaml +4 -4
- data/NEWS.md +27 -0
- data/lib/csv/fields_converter.rb +6 -2
- data/lib/csv/input_record_separator.rb +31 -0
- data/lib/csv/parser.rb +12 -10
- data/lib/csv/version.rb +1 -1
- data/lib/csv/writer.rb +2 -1
- data/lib/csv.rb +29 -8
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6aee33c500a979f9f1a9afdbc394545932700ca3442c1b4326b417e59b654ef4
|
4
|
+
data.tar.gz: 6622e0c4f190f10aa6d3a49b023a6c24540b1133da4d0ef91c07016ba224073f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7ba35310fd8dc9ffd4075ca31d786b7458fefefaee4c5a00fc326063fb13d020d1959d9970dcf17c222dd5d2422e3d20b9ddcd503caf5a4aad04e0b93159ff60
|
7
|
+
data.tar.gz: 9d1971baae109ad7396124cfa6bda15bc6db635ff09c6166a750dc22633b552679e5d589b15a57724f7b4aef3ae33c2ccd2fcfcfb1084e71df7f3734347e9926
|
data/NEWS.md
CHANGED
@@ -1,5 +1,32 @@
|
|
1
1
|
# News
|
2
2
|
|
3
|
+
## 3.2.1 - 2021-10-23
|
4
|
+
|
5
|
+
### Improvements
|
6
|
+
|
7
|
+
* doc: Fixed wrong class name.
|
8
|
+
[GitHub#217][Patch by Vince]
|
9
|
+
|
10
|
+
* Changed to always use `"\n"` for the default row separator on Ruby
|
11
|
+
3.0 or later because `$INPUT_RECORD_SEPARATOR` was deprecated
|
12
|
+
since Ruby 3.0.
|
13
|
+
|
14
|
+
* Added support for Ractor.
|
15
|
+
[GitHub#218][Patch by rm155]
|
16
|
+
|
17
|
+
* Users who want to use the built-in converters in non-main
|
18
|
+
Ractors need to call `Ractor.make_shareable(CSV::Converters)`
|
19
|
+
and/or `Ractor.make_shareable(CSV::HeaderConverters)` before
|
20
|
+
creating non-main Ractors.
|
21
|
+
|
22
|
+
### Thanks
|
23
|
+
|
24
|
+
* Vince
|
25
|
+
|
26
|
+
* Joakim Antman
|
27
|
+
|
28
|
+
* rm155
|
29
|
+
|
3
30
|
## 3.2.0 - 2021-06-06
|
4
31
|
|
5
32
|
### Improvements
|
data/lib/csv/fields_converter.rb
CHANGED
@@ -16,7 +16,7 @@ class CSV
|
|
16
16
|
@empty_value = options[:empty_value]
|
17
17
|
@empty_value_is_empty_string = (@empty_value == "")
|
18
18
|
@accept_nil = options[:accept_nil]
|
19
|
-
@
|
19
|
+
@builtin_converters_name = options[:builtin_converters_name]
|
20
20
|
@need_static_convert = need_static_convert?
|
21
21
|
end
|
22
22
|
|
@@ -24,7 +24,7 @@ class CSV
|
|
24
24
|
if name.nil? # custom converter
|
25
25
|
@converters << converter
|
26
26
|
else # named converter
|
27
|
-
combo =
|
27
|
+
combo = builtin_converters[name]
|
28
28
|
case combo
|
29
29
|
when Array # combo converter
|
30
30
|
combo.each do |sub_name|
|
@@ -80,5 +80,9 @@ class CSV
|
|
80
80
|
@need_static_convert or
|
81
81
|
(not @converters.empty?)
|
82
82
|
end
|
83
|
+
|
84
|
+
def builtin_converters
|
85
|
+
@builtin_converters ||= ::CSV.const_get(@builtin_converters_name)
|
86
|
+
end
|
83
87
|
end
|
84
88
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require "English"
|
2
|
+
require "stringio"
|
3
|
+
|
4
|
+
class CSV
|
5
|
+
module InputRecordSeparator
|
6
|
+
class << self
|
7
|
+
is_input_record_separator_deprecated = false
|
8
|
+
verbose, $VERBOSE = $VERBOSE, true
|
9
|
+
stderr, $stderr = $stderr, StringIO.new
|
10
|
+
input_record_separator = $INPUT_RECORD_SEPARATOR
|
11
|
+
begin
|
12
|
+
$INPUT_RECORD_SEPARATOR = "\r\n"
|
13
|
+
is_input_record_separator_deprecated = (not $stderr.string.empty?)
|
14
|
+
ensure
|
15
|
+
$INPUT_RECORD_SEPARATOR = input_record_separator
|
16
|
+
$stderr = stderr
|
17
|
+
$VERBOSE = verbose
|
18
|
+
end
|
19
|
+
|
20
|
+
if is_input_record_separator_deprecated
|
21
|
+
def value
|
22
|
+
"\n"
|
23
|
+
end
|
24
|
+
else
|
25
|
+
def value
|
26
|
+
$INPUT_RECORD_SEPARATOR
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/csv/parser.rb
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
require "strscan"
|
4
4
|
|
5
5
|
require_relative "delete_suffix"
|
6
|
+
require_relative "input_record_separator"
|
6
7
|
require_relative "match_p"
|
7
8
|
require_relative "row"
|
8
9
|
require_relative "table"
|
@@ -479,9 +480,9 @@ class CSV
|
|
479
480
|
begin
|
480
481
|
StringScanner.new("x").scan("x")
|
481
482
|
rescue TypeError
|
482
|
-
|
483
|
+
STRING_SCANNER_SCAN_ACCEPT_STRING = false
|
483
484
|
else
|
484
|
-
|
485
|
+
STRING_SCANNER_SCAN_ACCEPT_STRING = true
|
485
486
|
end
|
486
487
|
|
487
488
|
def prepare_separators
|
@@ -505,7 +506,7 @@ class CSV
|
|
505
506
|
@first_column_separators = Regexp.new(@escaped_first_column_separator +
|
506
507
|
"+".encode(@encoding))
|
507
508
|
else
|
508
|
-
if
|
509
|
+
if STRING_SCANNER_SCAN_ACCEPT_STRING
|
509
510
|
@column_end = @column_separator
|
510
511
|
else
|
511
512
|
@column_end = Regexp.new(@escaped_column_separator)
|
@@ -526,7 +527,7 @@ class CSV
|
|
526
527
|
|
527
528
|
@cr = "\r".encode(@encoding)
|
528
529
|
@lf = "\n".encode(@encoding)
|
529
|
-
@
|
530
|
+
@line_end = Regexp.new("\r\n|\n|\r".encode(@encoding))
|
530
531
|
@not_line_end = Regexp.new("[^\r\n]+".encode(@encoding))
|
531
532
|
end
|
532
533
|
|
@@ -605,7 +606,7 @@ class CSV
|
|
605
606
|
# do nothing: ensure will set default
|
606
607
|
end
|
607
608
|
end
|
608
|
-
separator =
|
609
|
+
separator = InputRecordSeparator.value if separator == :auto
|
609
610
|
end
|
610
611
|
separator.to_s.encode(@encoding)
|
611
612
|
end
|
@@ -724,6 +725,8 @@ class CSV
|
|
724
725
|
end
|
725
726
|
end
|
726
727
|
|
728
|
+
SCANNER_TEST_CHUNK_SIZE =
|
729
|
+
Integer((ENV["CSV_PARSER_SCANNER_TEST_CHUNK_SIZE"] || "1"), 10)
|
727
730
|
def build_scanner
|
728
731
|
inputs = @samples.collect do |sample|
|
729
732
|
UnoptimizedStringIO.new(sample)
|
@@ -733,10 +736,9 @@ class CSV
|
|
733
736
|
else
|
734
737
|
inputs << @input
|
735
738
|
end
|
736
|
-
chunk_size = ENV["CSV_PARSER_SCANNER_TEST_CHUNK_SIZE"] || "1"
|
737
739
|
InputsScanner.new(inputs,
|
738
740
|
@encoding,
|
739
|
-
chunk_size:
|
741
|
+
chunk_size: SCANNER_TEST_CHUNK_SIZE)
|
740
742
|
end
|
741
743
|
else
|
742
744
|
def build_scanner
|
@@ -914,7 +916,7 @@ class CSV
|
|
914
916
|
message = "Any value after quoted field isn't allowed"
|
915
917
|
raise MalformedCSVError.new(message, @lineno)
|
916
918
|
elsif @unquoted_column_value and
|
917
|
-
(new_line = @scanner.scan(@
|
919
|
+
(new_line = @scanner.scan(@line_end))
|
918
920
|
ignore_broken_line
|
919
921
|
message = "Unquoted fields do not allow new line " +
|
920
922
|
"<#{new_line.inspect}>"
|
@@ -923,7 +925,7 @@ class CSV
|
|
923
925
|
ignore_broken_line
|
924
926
|
message = "Illegal quoting"
|
925
927
|
raise MalformedCSVError.new(message, @lineno)
|
926
|
-
elsif (new_line = @scanner.scan(@
|
928
|
+
elsif (new_line = @scanner.scan(@line_end))
|
927
929
|
ignore_broken_line
|
928
930
|
message = "New line must be <#{@row_separator.inspect}> " +
|
929
931
|
"not <#{new_line.inspect}>"
|
@@ -1089,7 +1091,7 @@ class CSV
|
|
1089
1091
|
|
1090
1092
|
def ignore_broken_line
|
1091
1093
|
@scanner.scan_all(@not_line_end)
|
1092
|
-
@scanner.scan_all(@
|
1094
|
+
@scanner.scan_all(@line_end)
|
1093
1095
|
@lineno += 1
|
1094
1096
|
end
|
1095
1097
|
|
data/lib/csv/version.rb
CHANGED
data/lib/csv/writer.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative "input_record_separator"
|
3
4
|
require_relative "match_p"
|
4
5
|
require_relative "row"
|
5
6
|
|
@@ -133,7 +134,7 @@ class CSV
|
|
133
134
|
@column_separator = @options[:column_separator].to_s.encode(@encoding)
|
134
135
|
row_separator = @options[:row_separator]
|
135
136
|
if row_separator == :auto
|
136
|
-
@row_separator =
|
137
|
+
@row_separator = InputRecordSeparator.value.encode(@encoding)
|
137
138
|
else
|
138
139
|
@row_separator = row_separator.to_s.encode(@encoding)
|
139
140
|
end
|
data/lib/csv.rb
CHANGED
@@ -90,11 +90,11 @@
|
|
90
90
|
# with any questions.
|
91
91
|
|
92
92
|
require "forwardable"
|
93
|
-
require "English"
|
94
93
|
require "date"
|
95
94
|
require "stringio"
|
96
95
|
|
97
96
|
require_relative "csv/fields_converter"
|
97
|
+
require_relative "csv/input_record_separator"
|
98
98
|
require_relative "csv/match_p"
|
99
99
|
require_relative "csv/parser"
|
100
100
|
require_relative "csv/row"
|
@@ -513,7 +513,7 @@ using CSV::MatchP if CSV.const_defined?(:MatchP)
|
|
513
513
|
# [" 1 ", #<struct CSV::FieldInfo index=1, line=2, header=nil>]
|
514
514
|
# [" baz ", #<struct CSV::FieldInfo index=0, line=3, header=nil>]
|
515
515
|
# [" 2 ", #<struct CSV::FieldInfo index=1, line=3, header=nil>]
|
516
|
-
# Each CSV::
|
516
|
+
# Each CSV::FieldInfo object shows:
|
517
517
|
# - The 0-based field index.
|
518
518
|
# - The 1-based line index.
|
519
519
|
# - The field header, if any.
|
@@ -547,6 +547,14 @@ using CSV::MatchP if CSV.const_defined?(:MatchP)
|
|
547
547
|
#
|
548
548
|
# There is no such storage structure for write headers.
|
549
549
|
#
|
550
|
+
# In order for the parsing methods to access stored converters in non-main-Ractors, the
|
551
|
+
# storage structure must be made shareable first.
|
552
|
+
# Therefore, <tt>Ractor.make_shareable(CSV::Converters)</tt> and
|
553
|
+
# <tt>Ractor.make_shareable(CSV::HeaderConverters)</tt> must be called before the creation
|
554
|
+
# of Ractors that use the converters stored in these structures. (Since making the storage
|
555
|
+
# structures shareable involves freezing them, any custom converters that are to be used
|
556
|
+
# must be added first.)
|
557
|
+
#
|
550
558
|
# ===== Converter Lists
|
551
559
|
#
|
552
560
|
# A _converter_ _list_ is an \Array that may include any assortment of:
|
@@ -919,6 +927,7 @@ class CSV
|
|
919
927
|
gsub(/\s+/, "_").to_sym
|
920
928
|
}
|
921
929
|
}
|
930
|
+
|
922
931
|
# Default values for method options.
|
923
932
|
DEFAULT_OPTIONS = {
|
924
933
|
# For both parsing and generating.
|
@@ -957,6 +966,8 @@ class CSV
|
|
957
966
|
# Creates or retrieves cached \CSV objects.
|
958
967
|
# For arguments and options, see CSV.new.
|
959
968
|
#
|
969
|
+
# This API is not Ractor-safe.
|
970
|
+
#
|
960
971
|
# ---
|
961
972
|
#
|
962
973
|
# With no block given, returns a \CSV object.
|
@@ -1187,7 +1198,7 @@ class CSV
|
|
1187
1198
|
# See {Options for Parsing}[#class-CSV-label-Options+for+Parsing].
|
1188
1199
|
def filter(input=nil, output=nil, **options)
|
1189
1200
|
# parse options for input, output, or both
|
1190
|
-
in_options, out_options = Hash.new, {row_sep:
|
1201
|
+
in_options, out_options = Hash.new, {row_sep: InputRecordSeparator.value}
|
1191
1202
|
options.each do |key, value|
|
1192
1203
|
case key.to_s
|
1193
1204
|
when /\Ain(?:put)?_(.+)\Z/
|
@@ -1407,8 +1418,8 @@ class CSV
|
|
1407
1418
|
# Argument +ary+ must be an \Array.
|
1408
1419
|
#
|
1409
1420
|
# Special options:
|
1410
|
-
# * Option <tt>:row_sep</tt> defaults to <tt
|
1411
|
-
# (<tt>$/</tt>).:
|
1421
|
+
# * Option <tt>:row_sep</tt> defaults to <tt>"\n"> on Ruby 3.0 or later
|
1422
|
+
# and <tt>$INPUT_RECORD_SEPARATOR</tt> (<tt>$/</tt>) otherwise.:
|
1412
1423
|
# $INPUT_RECORD_SEPARATOR # => "\n"
|
1413
1424
|
# * This method accepts an additional option, <tt>:encoding</tt>, which sets the base
|
1414
1425
|
# Encoding for the output. This method will try to guess your Encoding from
|
@@ -1430,7 +1441,7 @@ class CSV
|
|
1430
1441
|
# CSV.generate_line(:foo)
|
1431
1442
|
#
|
1432
1443
|
def generate_line(row, **options)
|
1433
|
-
options = {row_sep:
|
1444
|
+
options = {row_sep: InputRecordSeparator.value}.merge(options)
|
1434
1445
|
str = +""
|
1435
1446
|
if options[:encoding]
|
1436
1447
|
str.force_encoding(options[:encoding])
|
@@ -1992,6 +2003,10 @@ class CSV
|
|
1992
2003
|
# csv.converters # => [:integer]
|
1993
2004
|
# csv.convert(proc {|x| x.to_s })
|
1994
2005
|
# csv.converters
|
2006
|
+
#
|
2007
|
+
# Notes that you need to call
|
2008
|
+
# +Ractor.make_shareable(CSV::Converters)+ on the main Ractor to use
|
2009
|
+
# this method.
|
1995
2010
|
def converters
|
1996
2011
|
parser_fields_converter.map do |converter|
|
1997
2012
|
name = Converters.rassoc(converter)
|
@@ -2054,6 +2069,10 @@ class CSV
|
|
2054
2069
|
# Returns an \Array containing header converters; used for parsing;
|
2055
2070
|
# see {Header Converters}[#class-CSV-label-Header+Converters]:
|
2056
2071
|
# CSV.new('').header_converters # => []
|
2072
|
+
#
|
2073
|
+
# Notes that you need to call
|
2074
|
+
# +Ractor.make_shareable(CSV::HeaderConverters)+ on the main Ractor
|
2075
|
+
# to use this method.
|
2057
2076
|
def header_converters
|
2058
2077
|
header_fields_converter.map do |converter|
|
2059
2078
|
name = HeaderConverters.rassoc(converter)
|
@@ -2694,7 +2713,7 @@ class CSV
|
|
2694
2713
|
|
2695
2714
|
def build_parser_fields_converter
|
2696
2715
|
specific_options = {
|
2697
|
-
|
2716
|
+
builtin_converters_name: :Converters,
|
2698
2717
|
}
|
2699
2718
|
options = @base_fields_converter_options.merge(specific_options)
|
2700
2719
|
build_fields_converter(@initial_converters, options)
|
@@ -2706,7 +2725,7 @@ class CSV
|
|
2706
2725
|
|
2707
2726
|
def build_header_fields_converter
|
2708
2727
|
specific_options = {
|
2709
|
-
|
2728
|
+
builtin_converters_name: :HeaderConverters,
|
2710
2729
|
accept_nil: true,
|
2711
2730
|
}
|
2712
2731
|
options = @base_fields_converter_options.merge(specific_options)
|
@@ -2774,6 +2793,8 @@ end
|
|
2774
2793
|
# io = StringIO.new
|
2775
2794
|
# CSV(io, col_sep: ";") { |csv| csv << ["a", "b", "c"] }
|
2776
2795
|
#
|
2796
|
+
# This API is not Ractor-safe.
|
2797
|
+
#
|
2777
2798
|
def CSV(*args, **options, &block)
|
2778
2799
|
CSV.instance(*args, **options, &block)
|
2779
2800
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: csv
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.2.
|
4
|
+
version: 3.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- James Edward Gray II
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2021-
|
12
|
+
date: 2021-10-22 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -59,14 +59,14 @@ dependencies:
|
|
59
59
|
requirements:
|
60
60
|
- - ">="
|
61
61
|
- !ruby/object:Gem::Version
|
62
|
-
version: 3.4.
|
62
|
+
version: 3.4.8
|
63
63
|
type: :development
|
64
64
|
prerelease: false
|
65
65
|
version_requirements: !ruby/object:Gem::Requirement
|
66
66
|
requirements:
|
67
67
|
- - ">="
|
68
68
|
- !ruby/object:Gem::Version
|
69
|
-
version: 3.4.
|
69
|
+
version: 3.4.8
|
70
70
|
description: The CSV library provides a complete interface to CSV files and data.
|
71
71
|
It offers tools to enable you to read and write to and from Strings or IO objects,
|
72
72
|
as needed.
|
@@ -118,6 +118,7 @@ files:
|
|
118
118
|
- lib/csv/core_ext/string.rb
|
119
119
|
- lib/csv/delete_suffix.rb
|
120
120
|
- lib/csv/fields_converter.rb
|
121
|
+
- lib/csv/input_record_separator.rb
|
121
122
|
- lib/csv/match_p.rb
|
122
123
|
- lib/csv/parser.rb
|
123
124
|
- lib/csv/row.rb
|