csv 3.1.3 → 3.1.4

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: 287ad200c61c1756e9386a9d910c9e16c3f876e3860d7a147d82ef3d2017ca72
4
- data.tar.gz: 98d1b16dfad00c08f5b07e0beb0d535c3e1777d9e01ecca9a2d21c2e5665eefb
3
+ metadata.gz: dad2154faebc0d08b471d1f5624752997374f8472dc2408756d7a78efb87d9c9
4
+ data.tar.gz: 9c6e071bcf07ab25aa0ff068030b42dbb47968d9f9e7aa5b04a1ff33ed12c2ea
5
5
  SHA512:
6
- metadata.gz: f0d55f65f559d083f570a3f72f27d5123c961cad244ea6b0b098c9f3e806474a5a8fc4335ada22f9031fa37664c05229428c6630ecc800709a7e0c90b72514ab
7
- data.tar.gz: 97f936a5e13547f9c362c66617f36ae9e3e84c7e611b105ea40b0f59442cec165d9382aa34a6c9eebb16b365c2fa12620d839396a2041ad0a97c878ed86a1da3
6
+ metadata.gz: 4da5b31e15b5c215d1f346c330a3d86ebea640cc4af4c33bd0aa238ac4b9b5cde2c72fc7edcd045de60f4cacb49a5ed8cbbf8a963a1a0750d16f5472faa95c1c
7
+ data.tar.gz: 83ee56fae5acb6afdb8d722e0c0182f17112a157a2ab6ad0b30a60d524fd146850a1afe360217c2e2b5af36335668716289612ae1817d98c77b2ea2c5d610240
data/NEWS.md CHANGED
@@ -1,5 +1,30 @@
1
1
  # News
2
2
 
3
+ ## 3.1.4 - 2020-05-17
4
+
5
+ ### Improvements
6
+
7
+ * Improved document.
8
+ [GitHub#122][Patch by Burdette Lamar]
9
+
10
+ * Stopped to dropping stack trace for exception caused by
11
+ `CSV.parse_line`.
12
+ [GitHub#120][Reported by Kyle d'Oliveira]
13
+
14
+ ### Fixes
15
+
16
+ * Fixed a bug that `:write_nil_value` or `:write_empty_value` don't
17
+ work with non `String` objects.
18
+ [GitHub#123][Reported by asm256]
19
+
20
+ ### Thanks
21
+
22
+ * Burdette Lamar
23
+
24
+ * asm256
25
+
26
+ * Kyle d'Oliveira
27
+
3
28
  ## 3.1.3 - 2020-05-09
4
29
 
5
30
  ### Improvements
data/lib/csv.rb CHANGED
@@ -103,7 +103,6 @@ require_relative "csv/writer"
103
103
 
104
104
  using CSV::MatchP if CSV.const_defined?(:MatchP)
105
105
 
106
- #
107
106
  # This class provides a complete interface to CSV files and data. It offers
108
107
  # tools to enable you to read and write to and from Strings or IO objects, as
109
108
  # needed.
@@ -179,9 +178,89 @@ using CSV::MatchP if CSV.const_defined?(:MatchP)
179
178
  # CSV($stderr) { |csv_err| csv_err << %w{my data here} } # to $stderr
180
179
  # CSV($stdin) { |csv_in| csv_in.each { |row| p row } } # from $stdin
181
180
  #
182
- # == Data Conversion
181
+ # == Options
182
+ #
183
+ # The default values for options are:
184
+ # DEFAULT_OPTIONS = {
185
+ # # For both parsing and generating.
186
+ # col_sep: ",",
187
+ # row_sep: :auto,
188
+ # quote_char: '"',
189
+ # # For parsing.
190
+ # field_size_limit: nil,
191
+ # converters: nil,
192
+ # unconverted_fields: nil,
193
+ # headers: false,
194
+ # return_headers: false,
195
+ # header_converters: nil,
196
+ # skip_blanks: false,
197
+ # skip_lines: nil,
198
+ # liberal_parsing: false,
199
+ # nil_value: nil,
200
+ # empty_value: "",
201
+ # # For generating.
202
+ # write_headers: nil,
203
+ # quote_empty: true,
204
+ # force_quotes: false,
205
+ # write_converters: nil,
206
+ # write_nil_value: nil,
207
+ # write_empty_value: "",
208
+ # strip: false,
209
+ # }
210
+ #
211
+ # === Options for Parsing
212
+ #
213
+ # :include: ../doc/col_sep.rdoc
214
+ #
215
+ # :include: ../doc/row_sep.rdoc
216
+ #
217
+ # :include: ../doc/quote_char.rdoc
218
+ #
219
+ # :include: ../doc/field_size_limit.rdoc
220
+ #
221
+ # :include: ../doc/converters.rdoc
222
+ #
223
+ # :include: ../doc/unconverted_fields.rdoc
224
+ #
225
+ # :include: ../doc/headers.rdoc
226
+ #
227
+ # :include: ../doc/return_headers.rdoc
228
+ #
229
+ # :include: ../doc/header_converters.rdoc
230
+ #
231
+ # :include: ../doc/skip_blanks.rdoc
232
+ #
233
+ # :include: ../doc/skip_lines.rdoc
234
+ #
235
+ # :include: ../doc/liberal_parsing.rdoc
236
+ #
237
+ # :include: ../doc/nil_value.rdoc
238
+ #
239
+ # :include: ../doc/empty_value.rdoc
240
+ #
241
+ # === Options for Generating
242
+ #
243
+ # :include: ../doc/col_sep.rdoc
244
+ #
245
+ # :include: ../doc/row_sep.rdoc
246
+ #
247
+ # :include: ../doc/quote_char.rdoc
248
+ #
249
+ # :include: ../doc/write_headers.rdoc
250
+ #
251
+ # :include: ../doc/force_quotes.rdoc
183
252
  #
184
- # === CSV with headers
253
+ # :include: ../doc/quote_empty.rdoc
254
+ #
255
+ # :include: ../doc/write_converters.rdoc
256
+ #
257
+ # :include: ../doc/write_nil_value.rdoc
258
+ #
259
+ # :include: ../doc/write_empty_value.rdoc
260
+ #
261
+ # :include: ../doc/strip.rdoc
262
+ #
263
+ # == CSV with headers
185
264
  #
186
265
  # CSV allows to specify column names of CSV file, whether they are in data, or
187
266
  # provided separately. If headers are specified, reading methods return an instance
@@ -203,22 +282,205 @@ using CSV::MatchP if CSV.const_defined?(:MatchP)
203
282
  # data = CSV.parse('Bob,Engineering,1000', headers: %i[name department salary])
204
283
  # data.first #=> #<CSV::Row name:"Bob" department:"Engineering" salary:"1000">
205
284
  #
206
- # === Typed data reading
207
- #
208
- # CSV allows to provide a set of data _converters_ e.g. transformations to try on input
209
- # data. Converter could be a symbol from CSV::Converters constant's keys, or lambda.
210
- #
211
- # # Without any converters:
212
- # CSV.parse('Bob,2018-03-01,100')
213
- # #=> [["Bob", "2018-03-01", "100"]]
214
- #
215
- # # With built-in converters:
216
- # CSV.parse('Bob,2018-03-01,100', converters: %i[numeric date])
217
- # #=> [["Bob", #<Date: 2018-03-01>, 100]]
218
- #
219
- # # With custom converters:
220
- # CSV.parse('Bob,2018-03-01,100', converters: [->(v) { Time.parse(v) rescue v }])
221
- # #=> [["Bob", 2018-03-01 00:00:00 +0200, "100"]]
285
+ # == \CSV \Converters
286
+ #
287
+ # By default, each field parsed by \CSV is formed into a \String.
288
+ # You can use a _converter_ to convert certain fields into other Ruby objects.
289
+ #
290
+ # When you specify a converter for parsing,
291
+ # each parsed field is passed to the converter;
292
+ # its return value becomes the new value for the field.
293
+ # A converter might, for example, convert an integer embedded in a \String
294
+ # into a true \Integer.
295
+ # (In fact, that's what built-in field converter +:integer+ does.)
296
+ #
297
+ # There are additional built-in \converters, and custom \converters are also supported.
298
+ #
299
+ # All \converters try to transcode fields to UTF-8 before converting.
300
+ # The conversion will fail if the data cannot be transcoded, leaving the field unchanged.
301
+ #
302
+ # === Field \Converters
303
+ #
304
+ # There are three ways to use field \converters;
305
+ # these examples use built-in field converter +:integer+,
306
+ # which converts each parsed integer string to a true \Integer.
307
+ #
308
+ # Option +converters+ with a singleton parsing method:
309
+ # ary = CSV.parse_line('0,1,2', converters: :integer)
310
+ # ary # => [0, 1, 2]
311
+ #
312
+ # Option +converters+ with a new \CSV instance:
313
+ # csv = CSV.new('0,1,2', converters: :integer)
314
+ # # Field converters in effect:
315
+ # csv.converters # => [:integer]
316
+ # csv.shift # => [0, 1, 2]
317
+ #
318
+ # Method #convert adds a field converter to a \CSV instance:
319
+ # csv = CSV.new('0,1,2')
320
+ # # Add a converter.
321
+ # csv.convert(:integer)
322
+ # csv.converters # => [:integer]
323
+ # csv.shift # => [0, 1, 2]
324
+ #
325
+ # ---
326
+ #
327
+ # The built-in field \converters are in \Hash CSV::Converters.
328
+ # The \Symbol keys there are the names of the \converters:
329
+ #
330
+ # CSV::Converters.keys # => [:integer, :float, :numeric, :date, :date_time, :all]
331
+ #
332
+ # Converter +:integer+ converts each field that +Integer()+ accepts:
333
+ # data = '0,1,2,x'
334
+ # # Without the converter
335
+ # csv = CSV.parse_line(data)
336
+ # csv # => ["0", "1", "2", "x"]
337
+ # # With the converter
338
+ # csv = CSV.parse_line(data, converters: :integer)
339
+ # csv # => [0, 1, 2, "x"]
340
+ #
341
+ # Converter +:float+ converts each field that +Float()+ accepts:
342
+ # data = '1.0,3.14159,x'
343
+ # # Without the converter
344
+ # csv = CSV.parse_line(data)
345
+ # csv # => ["1.0", "3.14159", "x"]
346
+ # # With the converter
347
+ # csv = CSV.parse_line(data, converters: :float)
348
+ # csv # => [1.0, 3.14159, "x"]
349
+ #
350
+ # Converter +:numeric+ converts with both +:integer+ and +:float+..
351
+ #
352
+ # Converter +:date+ converts each field that +Date::parse()+ accepts:
353
+ # data = '2001-02-03,x'
354
+ # # Without the converter
355
+ # csv = CSV.parse_line(data)
356
+ # csv # => ["2001-02-03", "x"]
357
+ # # With the converter
358
+ # csv = CSV.parse_line(data, converters: :date)
359
+ # csv # => [#<Date: 2001-02-03 ((2451944j,0s,0n),+0s,2299161j)>, "x"]
360
+ #
361
+ # Converter +:date_time+ converts each field that +DateTime::parse() accepts:
362
+ # data = '2020-05-07T14:59:00-05:00,x'
363
+ # # Without the converter
364
+ # csv = CSV.parse_line(data)
365
+ # csv # => ["2020-05-07T14:59:00-05:00", "x"]
366
+ # # With the converter
367
+ # csv = CSV.parse_line(data, converters: :date_time)
368
+ # csv # => [#<DateTime: 2020-05-07T14:59:00-05:00 ((2458977j,71940s,0n),-18000s,2299161j)>, "x"]
369
+ #
370
+ # Converter +:numeric+ converts with both +:date_time+ and +:numeric+..
371
+ #
372
+ # As seen above, method #convert adds \converters to a \CSV instance,
373
+ # and method #converters returns an \Array of the \converters in effect:
374
+ # csv = CSV.new('0,1,2')
375
+ # csv.converters # => []
376
+ # csv.convert(:integer)
377
+ # csv.converters # => [:integer]
378
+ # csv.convert(:date)
379
+ # csv.converters # => [:integer, :date]
380
+ #
381
+ # You can add a custom field converter to \Hash CSV::Converters:
382
+ # strip_converter = proc {|field| field.strip}
383
+ # CSV::Converters[:strip] = strip_converter
384
+ # CSV::Converters.keys # => [:integer, :float, :numeric, :date, :date_time, :all, :strip]
385
+ #
386
+ # Then use it to convert fields:
387
+ # str = ' foo , 0 '
388
+ # ary = CSV.parse_line(str, converters: :strip)
389
+ # ary # => ["foo", "0"]
390
+ #
391
+ # See {Custom Converters}[#class-CSV-label-Custom+Converters].
392
+ #
393
+ # === Header \Converters
394
+ #
395
+ # Header converters operate only on headers (and not on other rows).
396
+ #
397
+ # There are three ways to use header \converters;
398
+ # these examples use built-in header converter +:dowhcase+,
399
+ # which downcases each parsed header.
400
+ #
401
+ # Option +header_converters+ with a singleton parsing method:
402
+ # str = "Name,Count\nFoo,0\n,Bar,1\nBaz,2"
403
+ # tbl = CSV.parse(str, headers: true, header_converters: :downcase)
404
+ # tbl.class # => CSV::Table
405
+ # tbl.headers # => ["name", "count"]
406
+ #
407
+ # Option +header_converters+ with a new \CSV instance:
408
+ # csv = CSV.new(str, header_converters: :downcase)
409
+ # # Header converters in effect:
410
+ # csv.header_converters # => [:downcase]
411
+ # tbl = CSV.parse(str, headers: true)
412
+ # tbl.headers # => ["Name", "Count"]
413
+ #
414
+ # Method #header_convert adds a header converter to a \CSV instance:
415
+ # csv = CSV.new(str)
416
+ # # Add a header converter.
417
+ # csv.header_convert(:downcase)
418
+ # csv.header_converters # => [:downcase]
419
+ # tbl = CSV.parse(str, headers: true)
420
+ # tbl.headers # => ["Name", "Count"]
421
+ #
422
+ # ---
423
+ #
424
+ # The built-in header \converters are in \Hash CSV::Converters.
425
+ # The \Symbol keys there are the names of the \converters:
426
+ #
427
+ # CSV::HeaderConverters.keys # => [:downcase, :symbol]
428
+ #
429
+ # Converter +:downcase+ converts each header by downcasing it:
430
+ # str = "Name,Count\nFoo,0\n,Bar,1\nBaz,2"
431
+ # tbl = CSV.parse(str, headers: true, header_converters: :downcase)
432
+ # tbl.class # => CSV::Table
433
+ # tbl.headers # => ["name", "count"]
434
+ #
435
+ # Converter +:symbol+ by making it into a \Symbol:
436
+ # str = "Name,Count\nFoo,0\n,Bar,1\nBaz,2"
437
+ # tbl = CSV.parse(str, headers: true, header_converters: :symbol)
438
+ # tbl.headers # => [:name, :count]
439
+ # Details:
440
+ # - Strips leading and trailing whitespace.
441
+ # - Downcases the header.
442
+ # - Replaces embedded spaces with underscores.
443
+ # - Removes non-word characters.
444
+ # - Makes the string into a \Symbol.
445
+ #
446
+ # You can add a custom header converter to \Hash CSV::HeaderConverters:
447
+ # strip_converter = proc {|field| field.strip}
448
+ # CSV::HeaderConverters[:strip] = strip_converter
449
+ # CSV::HeaderConverters.keys # => [:downcase, :symbol, :strip]
450
+ #
451
+ # Then use it to convert headers:
452
+ # str = " Name , Value \nfoo,0\nbar,1\nbaz,2"
453
+ # tbl = CSV.parse(str, headers: true, header_converters: :strip)
454
+ # tbl.headers # => ["Name", "Value"]
455
+ #
456
+ # See {Custom Converters}[#class-CSV-label-Custom+Converters].
457
+ #
458
+ # === Custom \Converters
459
+ #
460
+ # You can define custom \converters.
461
+ #
462
+ # The \converter is a \Proc that is called with two arguments,
463
+ # \String +field+ and CSV::FieldInfo +field_info+;
464
+ # it returns a \String that will become the field value:
465
+ # converter = proc {|field, field_info| <some_string> }
466
+ #
467
+ # To illustrate:
468
+ # converter = proc {|field, field_info| p [field, field_info]; field}
469
+ # ary = CSV.parse_line('foo,0', converters: converter)
470
+ #
471
+ # Produces:
472
+ # ["foo", #<struct CSV::FieldInfo index=0, line=1, header=nil>]
473
+ # ["0", #<struct CSV::FieldInfo index=1, line=1, header=nil>]
474
+ #
475
+ # In each of the output lines:
476
+ # - The first \Array element is the passed \String field.
477
+ # - The second is a \FieldInfo structure containing information about the field:
478
+ # - The 0-based column index.
479
+ # - The 1-based line number.
480
+ # - The header for the column, if available.
481
+ #
482
+ # If the \converter does not need +field_info+, it can be omitted:
483
+ # converter = proc {|field| ... }
222
484
  #
223
485
  # == CSV and Character Encodings (M17n or Multilingualization)
224
486
  #
@@ -380,29 +642,13 @@ class CSV
380
642
  gsub(/\s+/, "_").to_sym
381
643
  }
382
644
  }
383
-
384
- #
385
- # The options used when no overrides are given by calling code. They are:
386
- #
387
- # <b><tt>:col_sep</tt></b>:: <tt>","</tt>
388
- # <b><tt>:row_sep</tt></b>:: <tt>:auto</tt>
389
- # <b><tt>:quote_char</tt></b>:: <tt>'"'</tt>
390
- # <b><tt>:field_size_limit</tt></b>:: +nil+
391
- # <b><tt>:converters</tt></b>:: +nil+
392
- # <b><tt>:unconverted_fields</tt></b>:: +nil+
393
- # <b><tt>:headers</tt></b>:: +false+
394
- # <b><tt>:return_headers</tt></b>:: +false+
395
- # <b><tt>:header_converters</tt></b>:: +nil+
396
- # <b><tt>:skip_blanks</tt></b>:: +false+
397
- # <b><tt>:force_quotes</tt></b>:: +false+
398
- # <b><tt>:skip_lines</tt></b>:: +nil+
399
- # <b><tt>:liberal_parsing</tt></b>:: +false+
400
- # <b><tt>:quote_empty</tt></b>:: +true+
401
- #
645
+ # Default values for method options.
402
646
  DEFAULT_OPTIONS = {
647
+ # For both parsing and generating.
403
648
  col_sep: ",",
404
649
  row_sep: :auto,
405
650
  quote_char: '"',
651
+ # For parsing.
406
652
  field_size_limit: nil,
407
653
  converters: nil,
408
654
  unconverted_fields: nil,
@@ -410,10 +656,18 @@ class CSV
410
656
  return_headers: false,
411
657
  header_converters: nil,
412
658
  skip_blanks: false,
413
- force_quotes: false,
414
659
  skip_lines: nil,
415
660
  liberal_parsing: false,
661
+ nil_value: nil,
662
+ empty_value: "",
663
+ # For generating.
664
+ write_headers: nil,
416
665
  quote_empty: true,
666
+ force_quotes: false,
667
+ write_converters: nil,
668
+ write_nil_value: nil,
669
+ write_empty_value: "",
670
+ strip: false,
417
671
  }.freeze
418
672
 
419
673
  class << self
@@ -423,6 +677,9 @@ class CSV
423
677
  # the same +data+ object (tested by Object#object_id()) with the same
424
678
  # +options+.
425
679
  #
680
+ # See {Options for Parsing}[#class-CSV-label-Options+for+Parsing]
681
+ # and {Options for Generating}[#class-CSV-label-Options+for+Generating].
682
+ #
426
683
  # If a block is given, the instance is passed to the block and the return
427
684
  # value becomes the return value of the block.
428
685
  #
@@ -463,6 +720,9 @@ class CSV
463
720
  # <tt>:out_</tt> or <tt>:output_</tt> affect only +output+. All other keys
464
721
  # are assigned to both objects.
465
722
  #
723
+ # See {Options for Parsing}[#class-CSV-label-Options+for+Parsing]
724
+ # and {Options for Generating}[#class-CSV-label-Options+for+Generating].
725
+ #
466
726
  # The <tt>:output_row_sep</tt> +option+ defaults to
467
727
  # <tt>$INPUT_RECORD_SEPARATOR</tt> (<tt>$/</tt>).
468
728
  #
@@ -496,6 +756,8 @@ class CSV
496
756
  # pass a +path+ and any +options+ you wish to set for the read. Each row of
497
757
  # file will be passed to the provided +block+ in turn.
498
758
  #
759
+ # See {Options for Parsing}[#class-CSV-label-Options+for+Parsing].
760
+ #
499
761
  # The +options+ parameter can be anything CSV::new() understands. This method
500
762
  # also understands an additional <tt>:encoding</tt> parameter that you can use
501
763
  # to specify the Encoding of the data in the file to be read. You must provide
@@ -525,10 +787,11 @@ class CSV
525
787
  # Note that a passed String *is* modified by this method. Call dup() before
526
788
  # passing if you need a new String.
527
789
  #
528
- # The +options+ parameter can be anything CSV::new() understands. This method
529
- # understands an additional <tt>:encoding</tt> parameter when not passed a
530
- # String to set the base Encoding for the output. CSV needs this hint if you
531
- # plan to output non-ASCII compatible data.
790
+ # See {Options for Generating}[#class-CSV-label-Options+for+Generating].
791
+ #
792
+ # This method has one additional option: <tt>:encoding</tt>,
793
+ # which sets the base Encoding for the output if no no +str+ is specified.
794
+ # CSV needs this hint if you plan to output non-ASCII compatible data.
532
795
  #
533
796
  def generate(str=nil, **options)
534
797
  encoding = options[:encoding]
@@ -550,8 +813,9 @@ class CSV
550
813
  # This method is a shortcut for converting a single row (Array) into a CSV
551
814
  # String.
552
815
  #
553
- # The +options+ parameter can be anything CSV::new() understands. This method
554
- # understands an additional <tt>:encoding</tt> parameter to set the base
816
+ # See {Options for Generating}[#class-CSV-label-Options+for+Generating].
817
+ #
818
+ # This method accepts an additional option, <tt>:encoding</tt>, which sets the base
555
819
  # Encoding for the output. This method will try to guess your Encoding from
556
820
  # the first non-+nil+ field in +row+, if possible, but you may need to use
557
821
  # this parameter as a backup plan.
@@ -581,8 +845,9 @@ class CSV
581
845
  # as the primary interface for writing a CSV file.
582
846
  #
583
847
  # You must pass a +filename+ and may optionally add a +mode+ for Ruby's
584
- # open(). You may also pass an optional Hash containing any +options+
585
- # CSV::new() understands as the final argument.
848
+ # open().
849
+ #
850
+ # See {Options for Generating}[#class-CSV-label-Options+for+Generating].
586
851
  #
587
852
  # This method works like Ruby's open() call, in that it will pass a CSV object
588
853
  # to a provided block and close it when the block terminates, or it will
@@ -674,8 +939,8 @@ class CSV
674
939
  # provide a +block+ which will be called with each row of the String in turn,
675
940
  # or just use the returned Array of Arrays (when no +block+ is given).
676
941
  #
677
- # You pass your +str+ to read from, and an optional +options+ containing
678
- # anything CSV::new() understands.
942
+ # You pass your +str+ to read from, and an optional +options+.
943
+ # See {Options for Parsing}[#class-CSV-label-Options+for+Parsing].
679
944
  #
680
945
  def parse(str, **options, &block)
681
946
  csv = new(str, **options)
@@ -695,15 +960,18 @@ class CSV
695
960
  # an Array. Note that if +line+ contains multiple rows, anything beyond the
696
961
  # first row is ignored.
697
962
  #
698
- # The +options+ parameter can be anything CSV::new() understands.
963
+ # See {Options for Parsing}[#class-CSV-label-Options+for+Parsing].
699
964
  #
700
965
  def parse_line(line, **options)
701
- new(line, **options).shift
966
+ new(line, **options).each.first
702
967
  end
703
968
 
704
969
  #
705
970
  # Use to slurp a CSV file into an Array of Arrays. Pass the +path+ to the
706
- # file and any +options+ CSV::new() understands. This method also understands
971
+ # file and +options+.
972
+ # See {Options for Parsing}[#class-CSV-label-Options+for+Parsing].
973
+ #
974
+ # This method also understands
707
975
  # an additional <tt>:encoding</tt> parameter that you can use to specify the
708
976
  # Encoding of the data in the file to be read. You must provide this unless
709
977
  # your data is in Encoding::default_external(). CSV will use this to determine
@@ -728,6 +996,7 @@ class CSV
728
996
  # converters: :numeric,
729
997
  # header_converters: :symbol }.merge(options) )
730
998
  #
999
+ # See {Options for Parsing}[#class-CSV-label-Options+for+Parsing].
731
1000
  def table(path, **options)
732
1001
  default_options = {
733
1002
  headers: true,
@@ -750,171 +1019,8 @@ class CSV
750
1019
  # reading). If you want it at the end (for writing), use CSV::generate().
751
1020
  # If you want any other positioning, pass a preset StringIO object instead.
752
1021
  #
753
- # You may set any reading and/or writing preferences in the +options+ Hash.
754
- # Available options are:
755
- #
756
- # <b><tt>:col_sep</tt></b>:: The String placed between each field.
757
- # This String will be transcoded into
758
- # the data's Encoding before parsing.
759
- # <b><tt>:row_sep</tt></b>:: The String appended to the end of each
760
- # row. This can be set to the special
761
- # <tt>:auto</tt> setting, which requests
762
- # that CSV automatically discover this
763
- # from the data. Auto-discovery reads
764
- # ahead in the data looking for the next
765
- # <tt>"\r\n"</tt>, <tt>"\n"</tt>, or
766
- # <tt>"\r"</tt> sequence. A sequence
767
- # will be selected even if it occurs in
768
- # a quoted field, assuming that you
769
- # would have the same line endings
770
- # there. If none of those sequences is
771
- # found, +data+ is <tt>ARGF</tt>,
772
- # <tt>STDIN</tt>, <tt>STDOUT</tt>, or
773
- # <tt>STDERR</tt>, or the stream is only
774
- # available for output, the default
775
- # <tt>$INPUT_RECORD_SEPARATOR</tt>
776
- # (<tt>$/</tt>) is used. Obviously,
777
- # discovery takes a little time. Set
778
- # manually if speed is important. Also
779
- # note that IO objects should be opened
780
- # in binary mode on Windows if this
781
- # feature will be used as the
782
- # line-ending translation can cause
783
- # problems with resetting the document
784
- # position to where it was before the
785
- # read ahead. This String will be
786
- # transcoded into the data's Encoding
787
- # before parsing.
788
- # <b><tt>:quote_char</tt></b>:: The character used to quote fields.
789
- # This has to be a single character
790
- # String. This is useful for
791
- # application that incorrectly use
792
- # <tt>'</tt> as the quote character
793
- # instead of the correct <tt>"</tt>.
794
- # CSV will always consider a double
795
- # sequence of this character to be an
796
- # escaped quote. This String will be
797
- # transcoded into the data's Encoding
798
- # before parsing.
799
- # <b><tt>:field_size_limit</tt></b>:: This is a maximum size CSV will read
800
- # ahead looking for the closing quote
801
- # for a field. (In truth, it reads to
802
- # the first line ending beyond this
803
- # size.) If a quote cannot be found
804
- # within the limit CSV will raise a
805
- # MalformedCSVError, assuming the data
806
- # is faulty. You can use this limit to
807
- # prevent what are effectively DoS
808
- # attacks on the parser. However, this
809
- # limit can cause a legitimate parse to
810
- # fail and thus is set to +nil+, or off,
811
- # by default.
812
- # <b><tt>:converters</tt></b>:: An Array of names from the Converters
813
- # Hash and/or lambdas that handle custom
814
- # conversion. A single converter
815
- # doesn't have to be in an Array. All
816
- # built-in converters try to transcode
817
- # fields to UTF-8 before converting.
818
- # The conversion will fail if the data
819
- # cannot be transcoded, leaving the
820
- # field unchanged.
821
- # <b><tt>:unconverted_fields</tt></b>:: If set to +true+, an
822
- # unconverted_fields() method will be
823
- # added to all returned rows (Array or
824
- # CSV::Row) that will return the fields
825
- # as they were before conversion. Note
826
- # that <tt>:headers</tt> supplied by
827
- # Array or String were not fields of the
828
- # document and thus will have an empty
829
- # Array attached.
830
- # <b><tt>:headers</tt></b>:: If set to <tt>:first_row</tt> or
831
- # +true+, the initial row of the CSV
832
- # file will be treated as a row of
833
- # headers. If set to an Array, the
834
- # contents will be used as the headers.
835
- # If set to a String, the String is run
836
- # through a call of CSV::parse_line()
837
- # with the same <tt>:col_sep</tt>,
838
- # <tt>:row_sep</tt>, and
839
- # <tt>:quote_char</tt> as this instance
840
- # to produce an Array of headers. This
841
- # setting causes CSV#shift() to return
842
- # rows as CSV::Row objects instead of
843
- # Arrays and CSV#read() to return
844
- # CSV::Table objects instead of an Array
845
- # of Arrays.
846
- # <b><tt>:return_headers</tt></b>:: When +false+, header rows are silently
847
- # swallowed. If set to +true+, header
848
- # rows are returned in a CSV::Row object
849
- # with identical headers and
850
- # fields (save that the fields do not go
851
- # through the converters).
852
- # <b><tt>:write_headers</tt></b>:: When +true+ and <tt>:headers</tt> is
853
- # set, a header row will be added to the
854
- # output.
855
- # <b><tt>:header_converters</tt></b>:: Identical in functionality to
856
- # <tt>:converters</tt> save that the
857
- # conversions are only made to header
858
- # rows. All built-in converters try to
859
- # transcode headers to UTF-8 before
860
- # converting. The conversion will fail
861
- # if the data cannot be transcoded,
862
- # leaving the header unchanged.
863
- # <b><tt>:skip_blanks</tt></b>:: When setting a +true+ value, CSV will
864
- # skip over any empty rows. Note that
865
- # this setting will not skip rows that
866
- # contain column separators, even if
867
- # the rows contain no actual data. If
868
- # you want to skip rows that contain
869
- # separators but no content, consider
870
- # using <tt>:skip_lines</tt>, or
871
- # inspecting fields.compact.empty? on
872
- # each row.
873
- # <b><tt>:force_quotes</tt></b>:: When setting a +true+ value, CSV will
874
- # quote all CSV fields it creates.
875
- # <b><tt>:skip_lines</tt></b>:: When setting an object responding to
876
- # <tt>match</tt>, every line matching
877
- # it is considered a comment and ignored
878
- # during parsing. When set to a String,
879
- # it is first converted to a Regexp.
880
- # When set to +nil+ no line is considered
881
- # a comment. If the passed object does
882
- # not respond to <tt>match</tt>,
883
- # <tt>ArgumentError</tt> is thrown.
884
- # <b><tt>:liberal_parsing</tt></b>:: When setting a +true+ value, CSV will
885
- # attempt to parse input not conformant
886
- # with RFC 4180, such as double quotes
887
- # in unquoted fields.
888
- # <b><tt>:nil_value</tt></b>:: When set an object, any values of an
889
- # empty field is replaced by the set
890
- # object, not nil.
891
- # <b><tt>:empty_value</tt></b>:: When setting an object, any values of a
892
- # blank string field is replaced by
893
- # the set object.
894
- # <b><tt>:quote_empty</tt></b>:: When setting a +true+ value, CSV will
895
- # quote empty values with double quotes.
896
- # When +false+, CSV will emit an
897
- # empty string for an empty field value.
898
- # <b><tt>:write_converters</tt></b>:: Converts values on each line with the
899
- # specified <tt>Proc</tt> object(s),
900
- # which receive a <tt>String</tt> value
901
- # and return a <tt>String</tt> or +nil+
902
- # value.
903
- # When an array is specified, each
904
- # converter will be applied in order.
905
- # <b><tt>:write_nil_value</tt></b>:: When a <tt>String</tt> value, +nil+
906
- # value(s) on each line will be replaced
907
- # with the specified value.
908
- # <b><tt>:write_empty_value</tt></b>:: When a <tt>String</tt> or +nil+ value,
909
- # empty value(s) on each line will be
910
- # replaced with the specified value.
911
- # <b><tt>:strip</tt></b>:: When setting a +true+ value, CSV will
912
- # strip " \t\f\v" around the values.
913
- # If you specify a string instead of
914
- # +true+, CSV will strip string. The
915
- # length of the string must be 1.
916
- #
917
- # See CSV::DEFAULT_OPTIONS for the default settings.
1022
+ # See {Options for Parsing}[#class-CSV-label-Options+for+Parsing]
1023
+ # and {Options for Generating}[#class-CSV-label-Options+for+Generating].
918
1024
  #
919
1025
  # Options cannot be overridden in the instance methods for performance reasons,
920
1026
  # so be sure to set what you want here.
@@ -50,7 +50,7 @@ class CSV
50
50
  fields.collect.with_index do |field, index|
51
51
  if field.nil?
52
52
  field = @nil_value
53
- elsif field.empty?
53
+ elsif field.is_a?(String) and field.empty?
54
54
  field = @empty_value unless @empty_value_is_empty_string
55
55
  end
56
56
  @converters.each do |converter|
@@ -708,7 +708,7 @@ class CSV
708
708
  if SCANNER_TEST
709
709
  class UnoptimizedStringIO
710
710
  def initialize(string)
711
- @io = StringIO.new(string)
711
+ @io = StringIO.new(string, "rb:#{string.encoding}")
712
712
  end
713
713
 
714
714
  def gets(*args)
@@ -2,5 +2,5 @@
2
2
 
3
3
  class CSV
4
4
  # The version of the installed library.
5
- VERSION = "3.1.3"
5
+ VERSION = "3.1.4"
6
6
  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.1.3
4
+ version: 3.1.4
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: 2020-05-08 00:00:00.000000000 Z
12
+ date: 2020-05-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler