csv 3.2.0 → 3.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c48c0d15454e002ff10270a9c56cf4311ce635a8a9dfb527f7a7541f29f801b2
4
- data.tar.gz: 505d1d0dbb4cff0a544b2e00925cb1101ed71642a584d534f443405fba8bd820
3
+ metadata.gz: 6aee33c500a979f9f1a9afdbc394545932700ca3442c1b4326b417e59b654ef4
4
+ data.tar.gz: 6622e0c4f190f10aa6d3a49b023a6c24540b1133da4d0ef91c07016ba224073f
5
5
  SHA512:
6
- metadata.gz: 1c9ecd18d5b9a4f663c0676694ffc133a4657e2f7a07cafe2f0a5d9ddd2d7846f505bc62c21698fcf1117126efc6978b7aa1b497d2fef8d532a8a4246c58bff2
7
- data.tar.gz: e4fe05b49f92c68c011060d1dcd39ead1785d886eabbd3689a12884df9eb30124694417314e39bcf656cd05d6d0dea6a80a701dd5fe6cac42efc33c67be54926
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
@@ -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
- @builtin_converters = options[:builtin_converters]
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 = @builtin_converters[name]
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
- @@string_scanner_scan_accept_string = false
483
+ STRING_SCANNER_SCAN_ACCEPT_STRING = false
483
484
  else
484
- @@string_scanner_scan_accept_string = true
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 @@string_scanner_scan_accept_string
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
- @cr_or_lf = Regexp.new("[\r\n]".encode(@encoding))
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 = $INPUT_RECORD_SEPARATOR if separator == :auto
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: Integer(chunk_size, 10))
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(@cr_or_lf))
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(@cr_or_lf))
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(@cr_or_lf)
1094
+ @scanner.scan_all(@line_end)
1093
1095
  @lineno += 1
1094
1096
  end
1095
1097
 
data/lib/csv/version.rb CHANGED
@@ -2,5 +2,5 @@
2
2
 
3
3
  class CSV
4
4
  # The version of the installed library.
5
- VERSION = "3.2.0"
5
+ VERSION = "3.2.1"
6
6
  end
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 = $INPUT_RECORD_SEPARATOR.encode(@encoding)
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::Info object shows:
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: $INPUT_RECORD_SEPARATOR}
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>$INPUT_RECORD_SEPARATOR</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: $INPUT_RECORD_SEPARATOR}.merge(options)
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
- builtin_converters: Converters,
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
- builtin_converters: HeaderConverters,
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.0
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-06-05 00:00:00.000000000 Z
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.3
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.3
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