csv 3.1.1 → 3.1.2

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: 9a4c5f1f8831a27754b3d84471e1d7f5813b516316d3c627f9ca341d469d9482
4
- data.tar.gz: 378c9f6b09fd19bc144431023b49ef16b4b476e710b297874b3ad5f2c2f2ed95
3
+ metadata.gz: 30015ee78d9fd5fa7b6bc0bbca7b785adef465e39dd654d4c4a020420f2f47ec
4
+ data.tar.gz: 72ece87ac30a9748dc64b37c8ca77de23b21939c19568c870b9ccb020f8cabf4
5
5
  SHA512:
6
- metadata.gz: ccced857c713eb59805cbc39d4fff7598caacd2ad0d1b2e5bd5d9f9011ee45348453309aaf0f768cd9d5bb7074649dd103a5f7422551e0f87cb9c306f8bcac6d
7
- data.tar.gz: 22d05da4348513414bee277ebb4739f66507278077a05dc60526362cb5c91ded284f24a4f1f01644935b525c6a6fcd728fad278a7e3d397d4ff724249663d550
6
+ metadata.gz: '09cdbbeb0d72c765d3cd15e690dfb6a25a7e731f5d79f15815cdc17cbb074c5d592d4805f9e59778f911478ea25dc635ee91a43210e8720e8c996166bbe4467c'
7
+ data.tar.gz: 8144fa3744620a731ff8b601316e476c6263a9928db41fa95ef50902d20928e1be174fbe115d42585a46dc455971e65fe1abc82032a9f6d82c959a675b1e252f
data/NEWS.md CHANGED
@@ -1,5 +1,52 @@
1
1
  # News
2
2
 
3
+ ## 3.1.2 - 2019-10-12
4
+
5
+ ### Improvements
6
+
7
+ * Added `:col_sep` check.
8
+ [GitHub#94][Reported by Florent Beaurain]
9
+
10
+ * Suppressed warnings.
11
+ [GitHub#96][Patch by Nobuyoshi Nakada]
12
+
13
+ * Improved documentation.
14
+ [GitHub#101][GitHub#102][Patch by Vitor Oliveira]
15
+
16
+ ### Fixes
17
+
18
+ * Fixed a typo in documentation.
19
+ [GitHub#95][Patch by Yuji Yaginuma]
20
+
21
+ * Fixed a multibyte character handling bug.
22
+ [GitHub#97][Patch by koshigoe]
23
+
24
+ * Fixed typos in documentation.
25
+ [GitHub#100][Patch by Vitor Oliveira]
26
+
27
+ * Fixed a bug that seeked `StringIO` isn't accepted.
28
+ [GitHub#98][Patch by MATSUMOTO Katsuyoshi]
29
+
30
+ * Fixed a bug that `CSV.generate_line` doesn't work with
31
+ `Encoding.default_internal`.
32
+ [GitHub#105][Reported by David Rodríguez]
33
+
34
+ ### Thanks
35
+
36
+ * Florent Beaurain
37
+
38
+ * Yuji Yaginuma
39
+
40
+ * Nobuyoshi Nakada
41
+
42
+ * koshigoe
43
+
44
+ * Vitor Oliveira
45
+
46
+ * MATSUMOTO Katsuyoshi
47
+
48
+ * David Rodríguez
49
+
3
50
  ## 3.1.1 - 2019-04-26
4
51
 
5
52
  ### Improvements
data/lib/csv.rb CHANGED
@@ -10,18 +10,18 @@
10
10
  #
11
11
  # Welcome to the new and improved CSV.
12
12
  #
13
- # This version of the CSV library began its life as FasterCSV. FasterCSV was
14
- # intended as a replacement to Ruby's then standard CSV library. It was
13
+ # This version of the CSV library began its life as FasterCSV. FasterCSV was
14
+ # intended as a replacement to Ruby's then standard CSV library. It was
15
15
  # designed to address concerns users of that library had and it had three
16
16
  # primary goals:
17
17
  #
18
18
  # 1. Be significantly faster than CSV while remaining a pure Ruby library.
19
- # 2. Use a smaller and easier to maintain code base. (FasterCSV eventually
20
- # grew larger, was also but considerably richer in features. The parsing
19
+ # 2. Use a smaller and easier to maintain code base. (FasterCSV eventually
20
+ # grew larger, was also but considerably richer in features. The parsing
21
21
  # core remains quite small.)
22
22
  # 3. Improve on the CSV interface.
23
23
  #
24
- # Obviously, the last one is subjective. I did try to defer to the original
24
+ # Obviously, the last one is subjective. I did try to defer to the original
25
25
  # interface whenever I didn't have a compelling reason to change it though, so
26
26
  # hopefully this won't be too radically different.
27
27
  #
@@ -29,20 +29,20 @@
29
29
  # the original library as of Ruby 1.9. If you are migrating code from 1.8 or
30
30
  # earlier, you may have to change your code to comply with the new interface.
31
31
  #
32
- # == What's Different From the Old CSV?
32
+ # == What's the Different From the Old CSV?
33
33
  #
34
34
  # I'm sure I'll miss something, but I'll try to mention most of the major
35
35
  # differences I am aware of, to help others quickly get up to speed:
36
36
  #
37
37
  # === CSV Parsing
38
38
  #
39
- # * This parser is m17n aware. See CSV for full details.
39
+ # * This parser is m17n aware. See CSV for full details.
40
40
  # * This library has a stricter parser and will throw MalformedCSVErrors on
41
41
  # problematic data.
42
- # * This library has a less liberal idea of a line ending than CSV. What you
43
- # set as the <tt>:row_sep</tt> is law. It can auto-detect your line endings
42
+ # * This library has a less liberal idea of a line ending than CSV. What you
43
+ # set as the <tt>:row_sep</tt> is law. It can auto-detect your line endings
44
44
  # though.
45
- # * The old library returned empty lines as <tt>[nil]</tt>. This library calls
45
+ # * The old library returned empty lines as <tt>[nil]</tt>. This library calls
46
46
  # them <tt>[]</tt>.
47
47
  # * This library has a much faster parser.
48
48
  #
@@ -56,9 +56,9 @@
56
56
  # * CSV now has a new() method used to wrap objects like String and IO for
57
57
  # reading and writing.
58
58
  # * CSV::generate() is different from the old method.
59
- # * CSV no longer supports partial reads. It works line-by-line.
59
+ # * CSV no longer supports partial reads. It works line-by-line.
60
60
  # * CSV no longer allows the instance methods to override the separators for
61
- # performance reasons. They must be set in the constructor.
61
+ # performance reasons. They must be set in the constructor.
62
62
  #
63
63
  # If you use this library and find yourself missing any functionality I have
64
64
  # trimmed, please {let me know}[mailto:james@grayproductions.net].
@@ -70,16 +70,16 @@
70
70
  # == What is CSV, really?
71
71
  #
72
72
  # CSV maintains a pretty strict definition of CSV taken directly from
73
- # {the RFC}[http://www.ietf.org/rfc/rfc4180.txt]. I relax the rules in only one
74
- # place and that is to make using this library easier. CSV will parse all valid
73
+ # {the RFC}[http://www.ietf.org/rfc/rfc4180.txt]. I relax the rules in only one
74
+ # place and that is to make using this library easier. CSV will parse all valid
75
75
  # CSV.
76
76
  #
77
- # What you don't want to do is feed CSV invalid data. Because of the way the
77
+ # What you don't want to do is to feed CSV invalid data. Because of the way the
78
78
  # CSV format works, it's common for a parser to need to read until the end of
79
- # the file to be sure a field is invalid. This eats a lot of time and memory.
79
+ # the file to be sure a field is invalid. This consumes a lot of time and memory.
80
80
  #
81
81
  # Luckily, when working with invalid CSV, Ruby's built-in methods will almost
82
- # always be superior in every way. For example, parsing non-quoted fields is as
82
+ # always be superior in every way. For example, parsing non-quoted fields is as
83
83
  # easy as:
84
84
  #
85
85
  # data.split(",")
@@ -104,7 +104,7 @@ require_relative "csv/writer"
104
104
  using CSV::MatchP if CSV.const_defined?(:MatchP)
105
105
 
106
106
  #
107
- # This class provides a complete interface to CSV files and data. It offers
107
+ # This class provides a complete interface to CSV files and data. It offers
108
108
  # tools to enable you to read and write to and from Strings or IO objects, as
109
109
  # needed.
110
110
  #
@@ -184,7 +184,7 @@ using CSV::MatchP if CSV.const_defined?(:MatchP)
184
184
  # === CSV with headers
185
185
  #
186
186
  # CSV allows to specify column names of CSV file, whether they are in data, or
187
- # provided separately. If headers specified, reading methods return an instance
187
+ # provided separately. If headers are specified, reading methods return an instance
188
188
  # of CSV::Table, consisting of CSV::Row.
189
189
  #
190
190
  # # Headers are part of data
@@ -200,7 +200,7 @@ using CSV::MatchP if CSV.const_defined?(:MatchP)
200
200
  # data.first.to_h #=> {"Name"=>"Bob", "Department"=>"Engineering", "Salary"=>"1000"}
201
201
  #
202
202
  # # Headers provided by developer
203
- # data = CSV.parse('Bob,Engeneering,1000', headers: %i[name department salary])
203
+ # data = CSV.parse('Bob,Engineering,1000', headers: %i[name department salary])
204
204
  # data.first #=> #<CSV::Row name:"Bob" department:"Engineering" salary:"1000">
205
205
  #
206
206
  # === Typed data reading
@@ -223,42 +223,42 @@ using CSV::MatchP if CSV.const_defined?(:MatchP)
223
223
  # == CSV and Character Encodings (M17n or Multilingualization)
224
224
  #
225
225
  # This new CSV parser is m17n savvy. The parser works in the Encoding of the IO
226
- # or String object being read from or written to. Your data is never transcoded
226
+ # or String object being read from or written to. Your data is never transcoded
227
227
  # (unless you ask Ruby to transcode it for you) and will literally be parsed in
228
- # the Encoding it is in. Thus CSV will return Arrays or Rows of Strings in the
229
- # Encoding of your data. This is accomplished by transcoding the parser itself
228
+ # the Encoding it is in. Thus CSV will return Arrays or Rows of Strings in the
229
+ # Encoding of your data. This is accomplished by transcoding the parser itself
230
230
  # into your Encoding.
231
231
  #
232
232
  # Some transcoding must take place, of course, to accomplish this multiencoding
233
- # support. For example, <tt>:col_sep</tt>, <tt>:row_sep</tt>, and
233
+ # support. For example, <tt>:col_sep</tt>, <tt>:row_sep</tt>, and
234
234
  # <tt>:quote_char</tt> must be transcoded to match your data. Hopefully this
235
235
  # makes the entire process feel transparent, since CSV's defaults should just
236
- # magically work for your data. However, you can set these values manually in
236
+ # magically work for your data. However, you can set these values manually in
237
237
  # the target Encoding to avoid the translation.
238
238
  #
239
239
  # It's also important to note that while all of CSV's core parser is now
240
- # Encoding agnostic, some features are not. For example, the built-in
240
+ # Encoding agnostic, some features are not. For example, the built-in
241
241
  # converters will try to transcode data to UTF-8 before making conversions.
242
242
  # Again, you can provide custom converters that are aware of your Encodings to
243
- # avoid this translation. It's just too hard for me to support native
243
+ # avoid this translation. It's just too hard for me to support native
244
244
  # conversions in all of Ruby's Encodings.
245
245
  #
246
- # Anyway, the practical side of this is simple: make sure IO and String objects
246
+ # Anyway, the practical side of this is simple: make sure IO and String objects
247
247
  # passed into CSV have the proper Encoding set and everything should just work.
248
248
  # CSV methods that allow you to open IO objects (CSV::foreach(), CSV::open(),
249
249
  # CSV::read(), and CSV::readlines()) do allow you to specify the Encoding.
250
250
  #
251
251
  # One minor exception comes when generating CSV into a String with an Encoding
252
- # that is not ASCII compatible. There's no existing data for CSV to use to
252
+ # that is not ASCII compatible. There's no existing data for CSV to use to
253
253
  # prepare itself and thus you will probably need to manually specify the desired
254
- # Encoding for most of those cases. It will try to guess using the fields in a
254
+ # Encoding for most of those cases. It will try to guess using the fields in a
255
255
  # row of output though, when using CSV::generate_line() or Array#to_csv().
256
256
  #
257
257
  # I try to point out any other Encoding issues in the documentation of methods
258
258
  # as they come up.
259
259
  #
260
260
  # This has been tested to the best of my ability with all non-"dummy" Encodings
261
- # Ruby ships with. However, it is brave new code and may have some bugs.
261
+ # Ruby ships with. However, it is brave new code and may have some bugs.
262
262
  # Please feel free to {report}[mailto:james@grayproductions.net] any issues you
263
263
  # find with it.
264
264
  #
@@ -354,7 +354,7 @@ class CSV
354
354
 
355
355
  #
356
356
  # This Hash holds the built-in header converters of CSV that can be accessed
357
- # by name. You can select HeaderConverters with CSV.header_convert() or
357
+ # by name. You can select HeaderConverters with CSV.header_convert() or
358
358
  # through the +options+ Hash passed to CSV::new().
359
359
  #
360
360
  # <b><tt>:downcase</tt></b>:: Calls downcase() on the header String.
@@ -364,13 +364,13 @@ class CSV
364
364
  # and finally to_sym() is called.
365
365
  #
366
366
  # All built-in header converters transcode header data to UTF-8 before
367
- # attempting a conversion. If your data cannot be transcoded to UTF-8 the
367
+ # attempting a conversion. If your data cannot be transcoded to UTF-8 the
368
368
  # conversion will fail and the header will remain unchanged.
369
369
  #
370
370
  # This Hash is intentionally left unfrozen and users should feel free to add
371
371
  # values to it that can be accessed by all CSV objects.
372
372
  #
373
- # To add a combo field, the value should be an Array of names. Combo fields
373
+ # To add a combo field, the value should be an Array of names. Combo fields
374
374
  # can be nested with other combo fields.
375
375
  #
376
376
  HeaderConverters = {
@@ -382,7 +382,7 @@ class CSV
382
382
  }
383
383
 
384
384
  #
385
- # The options used when no overrides are given by calling code. They are:
385
+ # The options used when no overrides are given by calling code. They are:
386
386
  #
387
387
  # <b><tt>:col_sep</tt></b>:: <tt>","</tt>
388
388
  # <b><tt>:row_sep</tt></b>:: <tt>:auto</tt>
@@ -416,331 +416,337 @@ class CSV
416
416
  quote_empty: true,
417
417
  }.freeze
418
418
 
419
- #
420
- # This method will return a CSV instance, just like CSV::new(), but the
421
- # instance will be cached and returned for all future calls to this method for
422
- # the same +data+ object (tested by Object#object_id()) with the same
423
- # +options+.
424
- #
425
- # If a block is given, the instance is passed to the block and the return
426
- # value becomes the return value of the block.
427
- #
428
- def self.instance(data = $stdout, **options)
429
- # create a _signature_ for this method call, data object and options
430
- sig = [data.object_id] +
431
- options.values_at(*DEFAULT_OPTIONS.keys.sort_by { |sym| sym.to_s })
432
-
433
- # fetch or create the instance for this signature
434
- @@instances ||= Hash.new
435
- instance = (@@instances[sig] ||= new(data, options))
436
-
437
- if block_given?
438
- yield instance # run block, if given, returning result
439
- else
440
- instance # or return the instance
419
+ class << self
420
+ #
421
+ # This method will return a CSV instance, just like CSV::new(), but the
422
+ # instance will be cached and returned for all future calls to this method for
423
+ # the same +data+ object (tested by Object#object_id()) with the same
424
+ # +options+.
425
+ #
426
+ # If a block is given, the instance is passed to the block and the return
427
+ # value becomes the return value of the block.
428
+ #
429
+ def instance(data = $stdout, **options)
430
+ # create a _signature_ for this method call, data object and options
431
+ sig = [data.object_id] +
432
+ options.values_at(*DEFAULT_OPTIONS.keys.sort_by { |sym| sym.to_s })
433
+
434
+ # fetch or create the instance for this signature
435
+ @@instances ||= Hash.new
436
+ instance = (@@instances[sig] ||= new(data, **options))
437
+
438
+ if block_given?
439
+ yield instance # run block, if given, returning result
440
+ else
441
+ instance # or return the instance
442
+ end
441
443
  end
442
- end
443
444
 
444
- #
445
- # :call-seq:
446
- # filter( **options ) { |row| ... }
447
- # filter( input, **options ) { |row| ... }
448
- # filter( input, output, **options ) { |row| ... }
449
- #
450
- # This method is a convenience for building Unix-like filters for CSV data.
451
- # Each row is yielded to the provided block which can alter it as needed.
452
- # After the block returns, the row is appended to +output+ altered or not.
453
- #
454
- # The +input+ and +output+ arguments can be anything CSV::new() accepts
455
- # (generally String or IO objects). If not given, they default to
456
- # <tt>ARGF</tt> and <tt>$stdout</tt>.
457
- #
458
- # The +options+ parameter is also filtered down to CSV::new() after some
459
- # clever key parsing. Any key beginning with <tt>:in_</tt> or
460
- # <tt>:input_</tt> will have that leading identifier stripped and will only
461
- # be used in the +options+ Hash for the +input+ object. Keys starting with
462
- # <tt>:out_</tt> or <tt>:output_</tt> affect only +output+. All other keys
463
- # are assigned to both objects.
464
- #
465
- # The <tt>:output_row_sep</tt> +option+ defaults to
466
- # <tt>$INPUT_RECORD_SEPARATOR</tt> (<tt>$/</tt>).
467
- #
468
- def self.filter(input=nil, output=nil, **options)
469
- # parse options for input, output, or both
470
- in_options, out_options = Hash.new, {row_sep: $INPUT_RECORD_SEPARATOR}
471
- options.each do |key, value|
472
- case key.to_s
473
- when /\Ain(?:put)?_(.+)\Z/
474
- in_options[$1.to_sym] = value
475
- when /\Aout(?:put)?_(.+)\Z/
476
- out_options[$1.to_sym] = value
477
- else
478
- in_options[key] = value
479
- out_options[key] = value
445
+ #
446
+ # :call-seq:
447
+ # filter( **options ) { |row| ... }
448
+ # filter( input, **options ) { |row| ... }
449
+ # filter( input, output, **options ) { |row| ... }
450
+ #
451
+ # This method is a convenience for building Unix-like filters for CSV data.
452
+ # Each row is yielded to the provided block which can alter it as needed.
453
+ # After the block returns, the row is appended to +output+ altered or not.
454
+ #
455
+ # The +input+ and +output+ arguments can be anything CSV::new() accepts
456
+ # (generally String or IO objects). If not given, they default to
457
+ # <tt>ARGF</tt> and <tt>$stdout</tt>.
458
+ #
459
+ # The +options+ parameter is also filtered down to CSV::new() after some
460
+ # clever key parsing. Any key beginning with <tt>:in_</tt> or
461
+ # <tt>:input_</tt> will have that leading identifier stripped and will only
462
+ # be used in the +options+ Hash for the +input+ object. Keys starting with
463
+ # <tt>:out_</tt> or <tt>:output_</tt> affect only +output+. All other keys
464
+ # are assigned to both objects.
465
+ #
466
+ # The <tt>:output_row_sep</tt> +option+ defaults to
467
+ # <tt>$INPUT_RECORD_SEPARATOR</tt> (<tt>$/</tt>).
468
+ #
469
+ def filter(input=nil, output=nil, **options)
470
+ # parse options for input, output, or both
471
+ in_options, out_options = Hash.new, {row_sep: $INPUT_RECORD_SEPARATOR}
472
+ options.each do |key, value|
473
+ case key.to_s
474
+ when /\Ain(?:put)?_(.+)\Z/
475
+ in_options[$1.to_sym] = value
476
+ when /\Aout(?:put)?_(.+)\Z/
477
+ out_options[$1.to_sym] = value
478
+ else
479
+ in_options[key] = value
480
+ out_options[key] = value
481
+ end
482
+ end
483
+ # build input and output wrappers
484
+ input = new(input || ARGF, **in_options)
485
+ output = new(output || $stdout, **out_options)
486
+
487
+ # read, yield, write
488
+ input.each do |row|
489
+ yield row
490
+ output << row
480
491
  end
481
492
  end
482
- # build input and output wrappers
483
- input = new(input || ARGF, in_options)
484
- output = new(output || $stdout, out_options)
485
-
486
- # read, yield, write
487
- input.each do |row|
488
- yield row
489
- output << row
493
+
494
+ #
495
+ # This method is intended as the primary interface for reading CSV files. You
496
+ # pass a +path+ and any +options+ you wish to set for the read. Each row of
497
+ # file will be passed to the provided +block+ in turn.
498
+ #
499
+ # The +options+ parameter can be anything CSV::new() understands. This method
500
+ # also understands an additional <tt>:encoding</tt> parameter that you can use
501
+ # to specify the Encoding of the data in the file to be read. You must provide
502
+ # this unless your data is in Encoding::default_external(). CSV will use this
503
+ # to determine how to parse the data. You may provide a second Encoding to
504
+ # have the data transcoded as it is read. For example,
505
+ # <tt>encoding: "UTF-32BE:UTF-8"</tt> would read UTF-32BE data from the file
506
+ # but transcode it to UTF-8 before CSV parses it.
507
+ #
508
+ def foreach(path, mode="r", **options, &block)
509
+ return to_enum(__method__, path, mode, **options) unless block_given?
510
+ open(path, mode, **options) do |csv|
511
+ csv.each(&block)
512
+ end
490
513
  end
491
- end
492
514
 
493
- #
494
- # This method is intended as the primary interface for reading CSV files. You
495
- # pass a +path+ and any +options+ you wish to set for the read. Each row of
496
- # file will be passed to the provided +block+ in turn.
497
- #
498
- # The +options+ parameter can be anything CSV::new() understands. This method
499
- # also understands an additional <tt>:encoding</tt> parameter that you can use
500
- # to specify the Encoding of the data in the file to be read. You must provide
501
- # this unless your data is in Encoding::default_external(). CSV will use this
502
- # to determine how to parse the data. You may provide a second Encoding to
503
- # have the data transcoded as it is read. For example,
504
- # <tt>encoding: "UTF-32BE:UTF-8"</tt> would read UTF-32BE data from the file
505
- # but transcode it to UTF-8 before CSV parses it.
506
- #
507
- def self.foreach(path, mode="r", **options, &block)
508
- return to_enum(__method__, path, mode, options) unless block_given?
509
- open(path, mode, options) do |csv|
510
- csv.each(&block)
515
+ #
516
+ # :call-seq:
517
+ # generate( str, **options ) { |csv| ... }
518
+ # generate( **options ) { |csv| ... }
519
+ #
520
+ # This method wraps a String you provide, or an empty default String, in a
521
+ # CSV object which is passed to the provided block. You can use the block to
522
+ # append CSV rows to the String and when the block exits, the final String
523
+ # will be returned.
524
+ #
525
+ # Note that a passed String *is* modified by this method. Call dup() before
526
+ # passing if you need a new String.
527
+ #
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.
532
+ #
533
+ def generate(str=nil, **options)
534
+ # add a default empty String, if none was given
535
+ if str
536
+ str = StringIO.new(str)
537
+ str.seek(0, IO::SEEK_END)
538
+ else
539
+ encoding = options[:encoding]
540
+ str = +""
541
+ str.force_encoding(encoding) if encoding
542
+ end
543
+ csv = new(str, **options) # wrap
544
+ yield csv # yield for appending
545
+ csv.string # return final String
511
546
  end
512
- end
513
547
 
514
- #
515
- # :call-seq:
516
- # generate( str, **options ) { |csv| ... }
517
- # generate( **options ) { |csv| ... }
518
- #
519
- # This method wraps a String you provide, or an empty default String, in a
520
- # CSV object which is passed to the provided block. You can use the block to
521
- # append CSV rows to the String and when the block exits, the final String
522
- # will be returned.
523
- #
524
- # Note that a passed String *is* modified by this method. Call dup() before
525
- # passing if you need a new String.
526
- #
527
- # The +options+ parameter can be anything CSV::new() understands. This method
528
- # understands an additional <tt>:encoding</tt> parameter when not passed a
529
- # String to set the base Encoding for the output. CSV needs this hint if you
530
- # plan to output non-ASCII compatible data.
531
- #
532
- def self.generate(str=nil, **options)
533
- # add a default empty String, if none was given
534
- if str
535
- str = StringIO.new(str)
536
- str.seek(0, IO::SEEK_END)
537
- else
538
- encoding = options[:encoding]
548
+ #
549
+ # This method is a shortcut for converting a single row (Array) into a CSV
550
+ # String.
551
+ #
552
+ # The +options+ parameter can be anything CSV::new() understands. This method
553
+ # understands an additional <tt>:encoding</tt> parameter to set the base
554
+ # Encoding for the output. This method will try to guess your Encoding from
555
+ # the first non-+nil+ field in +row+, if possible, but you may need to use
556
+ # this parameter as a backup plan.
557
+ #
558
+ # The <tt>:row_sep</tt> +option+ defaults to <tt>$INPUT_RECORD_SEPARATOR</tt>
559
+ # (<tt>$/</tt>) when calling this method.
560
+ #
561
+ def generate_line(row, **options)
562
+ options = {row_sep: $INPUT_RECORD_SEPARATOR}.merge(options)
539
563
  str = +""
540
- str.force_encoding(encoding) if encoding
564
+ if options[:encoding]
565
+ str.force_encoding(options[:encoding])
566
+ elsif field = row.find {|f| f.is_a?(String)}
567
+ str.force_encoding(field.encoding)
568
+ end
569
+ (new(str, **options) << row).string
541
570
  end
542
- csv = new(str, options) # wrap
543
- yield csv # yield for appending
544
- csv.string # return final String
545
- end
546
571
 
547
- #
548
- # This method is a shortcut for converting a single row (Array) into a CSV
549
- # String.
550
- #
551
- # The +options+ parameter can be anything CSV::new() understands. This method
552
- # understands an additional <tt>:encoding</tt> parameter to set the base
553
- # Encoding for the output. This method will try to guess your Encoding from
554
- # the first non-+nil+ field in +row+, if possible, but you may need to use
555
- # this parameter as a backup plan.
556
- #
557
- # The <tt>:row_sep</tt> +option+ defaults to <tt>$INPUT_RECORD_SEPARATOR</tt>
558
- # (<tt>$/</tt>) when calling this method.
559
- #
560
- def self.generate_line(row, **options)
561
- options = {row_sep: $INPUT_RECORD_SEPARATOR}.merge(options)
562
- str = +""
563
- if options[:encoding]
564
- str.force_encoding(options[:encoding])
565
- elsif field = row.find {|f| f.is_a?(String)}
566
- str.force_encoding(field.encoding)
567
- end
568
- (new(str, options) << row).string
569
- end
572
+ #
573
+ # :call-seq:
574
+ # open( filename, mode = "rb", **options ) { |faster_csv| ... }
575
+ # open( filename, **options ) { |faster_csv| ... }
576
+ # open( filename, mode = "rb", **options )
577
+ # open( filename, **options )
578
+ #
579
+ # This method opens an IO object, and wraps that with CSV. This is intended
580
+ # as the primary interface for writing a CSV file.
581
+ #
582
+ # You must pass a +filename+ and may optionally add a +mode+ for Ruby's
583
+ # open(). You may also pass an optional Hash containing any +options+
584
+ # CSV::new() understands as the final argument.
585
+ #
586
+ # This method works like Ruby's open() call, in that it will pass a CSV object
587
+ # to a provided block and close it when the block terminates, or it will
588
+ # return the CSV object when no block is provided. (*Note*: This is different
589
+ # from the Ruby 1.8 CSV library which passed rows to the block. Use
590
+ # CSV::foreach() for that behavior.)
591
+ #
592
+ # You must provide a +mode+ with an embedded Encoding designator unless your
593
+ # data is in Encoding::default_external(). CSV will check the Encoding of the
594
+ # underlying IO object (set by the +mode+ you pass) to determine how to parse
595
+ # the data. You may provide a second Encoding to have the data transcoded as
596
+ # it is read just as you can with a normal call to IO::open(). For example,
597
+ # <tt>"rb:UTF-32BE:UTF-8"</tt> would read UTF-32BE data from the file but
598
+ # transcode it to UTF-8 before CSV parses it.
599
+ #
600
+ # An opened CSV object will delegate to many IO methods for convenience. You
601
+ # may call:
602
+ #
603
+ # * binmode()
604
+ # * binmode?()
605
+ # * close()
606
+ # * close_read()
607
+ # * close_write()
608
+ # * closed?()
609
+ # * eof()
610
+ # * eof?()
611
+ # * external_encoding()
612
+ # * fcntl()
613
+ # * fileno()
614
+ # * flock()
615
+ # * flush()
616
+ # * fsync()
617
+ # * internal_encoding()
618
+ # * ioctl()
619
+ # * isatty()
620
+ # * path()
621
+ # * pid()
622
+ # * pos()
623
+ # * pos=()
624
+ # * reopen()
625
+ # * seek()
626
+ # * stat()
627
+ # * sync()
628
+ # * sync=()
629
+ # * tell()
630
+ # * to_i()
631
+ # * to_io()
632
+ # * truncate()
633
+ # * tty?()
634
+ #
635
+ def open(filename, mode="r", **options)
636
+ # wrap a File opened with the remaining +args+ with no newline
637
+ # decorator
638
+ file_opts = {universal_newline: false}.merge(options)
570
639
 
571
- #
572
- # :call-seq:
573
- # open( filename, mode = "rb", **options ) { |faster_csv| ... }
574
- # open( filename, **options ) { |faster_csv| ... }
575
- # open( filename, mode = "rb", **options )
576
- # open( filename, **options )
577
- #
578
- # This method opens an IO object, and wraps that with CSV. This is intended
579
- # as the primary interface for writing a CSV file.
580
- #
581
- # You must pass a +filename+ and may optionally add a +mode+ for Ruby's
582
- # open(). You may also pass an optional Hash containing any +options+
583
- # CSV::new() understands as the final argument.
584
- #
585
- # This method works like Ruby's open() call, in that it will pass a CSV object
586
- # to a provided block and close it when the block terminates, or it will
587
- # return the CSV object when no block is provided. (*Note*: This is different
588
- # from the Ruby 1.8 CSV library which passed rows to the block. Use
589
- # CSV::foreach() for that behavior.)
590
- #
591
- # You must provide a +mode+ with an embedded Encoding designator unless your
592
- # data is in Encoding::default_external(). CSV will check the Encoding of the
593
- # underlying IO object (set by the +mode+ you pass) to determine how to parse
594
- # the data. You may provide a second Encoding to have the data transcoded as
595
- # it is read just as you can with a normal call to IO::open(). For example,
596
- # <tt>"rb:UTF-32BE:UTF-8"</tt> would read UTF-32BE data from the file but
597
- # transcode it to UTF-8 before CSV parses it.
598
- #
599
- # An opened CSV object will delegate to many IO methods for convenience. You
600
- # may call:
601
- #
602
- # * binmode()
603
- # * binmode?()
604
- # * close()
605
- # * close_read()
606
- # * close_write()
607
- # * closed?()
608
- # * eof()
609
- # * eof?()
610
- # * external_encoding()
611
- # * fcntl()
612
- # * fileno()
613
- # * flock()
614
- # * flush()
615
- # * fsync()
616
- # * internal_encoding()
617
- # * ioctl()
618
- # * isatty()
619
- # * path()
620
- # * pid()
621
- # * pos()
622
- # * pos=()
623
- # * reopen()
624
- # * seek()
625
- # * stat()
626
- # * sync()
627
- # * sync=()
628
- # * tell()
629
- # * to_i()
630
- # * to_io()
631
- # * truncate()
632
- # * tty?()
633
- #
634
- def self.open(filename, mode="r", **options)
635
- # wrap a File opened with the remaining +args+ with no newline
636
- # decorator
637
- file_opts = {universal_newline: false}.merge(options)
640
+ begin
641
+ f = File.open(filename, mode, **file_opts)
642
+ rescue ArgumentError => e
643
+ raise unless /needs binmode/.match?(e.message) and mode == "r"
644
+ mode = "rb"
645
+ file_opts = {encoding: Encoding.default_external}.merge(file_opts)
646
+ retry
647
+ end
648
+ begin
649
+ csv = new(f, **options)
650
+ rescue Exception
651
+ f.close
652
+ raise
653
+ end
638
654
 
639
- begin
640
- f = File.open(filename, mode, file_opts)
641
- rescue ArgumentError => e
642
- raise unless /needs binmode/.match?(e.message) and mode == "r"
643
- mode = "rb"
644
- file_opts = {encoding: Encoding.default_external}.merge(file_opts)
645
- retry
646
- end
647
- begin
648
- csv = new(f, options)
649
- rescue Exception
650
- f.close
651
- raise
655
+ # handle blocks like Ruby's open(), not like the CSV library
656
+ if block_given?
657
+ begin
658
+ yield csv
659
+ ensure
660
+ csv.close
661
+ end
662
+ else
663
+ csv
664
+ end
652
665
  end
653
666
 
654
- # handle blocks like Ruby's open(), not like the CSV library
655
- if block_given?
667
+ #
668
+ # :call-seq:
669
+ # parse( str, **options ) { |row| ... }
670
+ # parse( str, **options )
671
+ #
672
+ # This method can be used to easily parse CSV out of a String. You may either
673
+ # provide a +block+ which will be called with each row of the String in turn,
674
+ # or just use the returned Array of Arrays (when no +block+ is given).
675
+ #
676
+ # You pass your +str+ to read from, and an optional +options+ containing
677
+ # anything CSV::new() understands.
678
+ #
679
+ def parse(str, **options, &block)
680
+ csv = new(str, **options)
681
+
682
+ return csv.each(&block) if block_given?
683
+
684
+ # slurp contents, if no block is given
656
685
  begin
657
- yield csv
686
+ csv.read
658
687
  ensure
659
688
  csv.close
660
689
  end
661
- else
662
- csv
663
690
  end
664
- end
665
-
666
- #
667
- # :call-seq:
668
- # parse( str, **options ) { |row| ... }
669
- # parse( str, **options )
670
- #
671
- # This method can be used to easily parse CSV out of a String. You may either
672
- # provide a +block+ which will be called with each row of the String in turn,
673
- # or just use the returned Array of Arrays (when no +block+ is given).
674
- #
675
- # You pass your +str+ to read from, and an optional +options+ containing
676
- # anything CSV::new() understands.
677
- #
678
- def self.parse(*args, &block)
679
- csv = new(*args)
680
-
681
- return csv.each(&block) if block_given?
682
691
 
683
- # slurp contents, if no block is given
684
- begin
685
- csv.read
686
- ensure
687
- csv.close
692
+ #
693
+ # This method is a shortcut for converting a single line of a CSV String into
694
+ # an Array. Note that if +line+ contains multiple rows, anything beyond the
695
+ # first row is ignored.
696
+ #
697
+ # The +options+ parameter can be anything CSV::new() understands.
698
+ #
699
+ def parse_line(line, **options)
700
+ new(line, **options).shift
688
701
  end
689
- end
690
702
 
691
- #
692
- # This method is a shortcut for converting a single line of a CSV String into
693
- # an Array. Note that if +line+ contains multiple rows, anything beyond the
694
- # first row is ignored.
695
- #
696
- # The +options+ parameter can be anything CSV::new() understands.
697
- #
698
- def self.parse_line(line, **options)
699
- new(line, options).shift
700
- end
701
-
702
- #
703
- # Use to slurp a CSV file into an Array of Arrays. Pass the +path+ to the
704
- # file and any +options+ CSV::new() understands. This method also understands
705
- # an additional <tt>:encoding</tt> parameter that you can use to specify the
706
- # Encoding of the data in the file to be read. You must provide this unless
707
- # your data is in Encoding::default_external(). CSV will use this to determine
708
- # how to parse the data. You may provide a second Encoding to have the data
709
- # transcoded as it is read. For example,
710
- # <tt>encoding: "UTF-32BE:UTF-8"</tt> would read UTF-32BE data from the file
711
- # but transcode it to UTF-8 before CSV parses it.
712
- #
713
- def self.read(path, *options)
714
- open(path, *options) { |csv| csv.read }
715
- end
703
+ #
704
+ # Use to slurp a CSV file into an Array of Arrays. Pass the +path+ to the
705
+ # file and any +options+ CSV::new() understands. This method also understands
706
+ # an additional <tt>:encoding</tt> parameter that you can use to specify the
707
+ # Encoding of the data in the file to be read. You must provide this unless
708
+ # your data is in Encoding::default_external(). CSV will use this to determine
709
+ # how to parse the data. You may provide a second Encoding to have the data
710
+ # transcoded as it is read. For example,
711
+ # <tt>encoding: "UTF-32BE:UTF-8"</tt> would read UTF-32BE data from the file
712
+ # but transcode it to UTF-8 before CSV parses it.
713
+ #
714
+ def read(path, **options)
715
+ open(path, **options) { |csv| csv.read }
716
+ end
716
717
 
717
- # Alias for CSV::read().
718
- def self.readlines(*args)
719
- read(*args)
720
- end
718
+ # Alias for CSV::read().
719
+ def readlines(path, **options)
720
+ read(path, **options)
721
+ end
721
722
 
722
- #
723
- # A shortcut for:
724
- #
725
- # CSV.read( path, { headers: true,
726
- # converters: :numeric,
727
- # header_converters: :symbol }.merge(options) )
728
- #
729
- def self.table(path, **options)
730
- read( path, { headers: true,
731
- converters: :numeric,
732
- header_converters: :symbol }.merge(options) )
723
+ #
724
+ # A shortcut for:
725
+ #
726
+ # CSV.read( path, { headers: true,
727
+ # converters: :numeric,
728
+ # header_converters: :symbol }.merge(options) )
729
+ #
730
+ def table(path, **options)
731
+ default_options = {
732
+ headers: true,
733
+ converters: :numeric,
734
+ header_converters: :symbol,
735
+ }
736
+ options = default_options.merge(options)
737
+ read(path, **options)
738
+ end
733
739
  end
734
740
 
735
741
  #
736
742
  # This constructor will wrap either a String or IO object passed in +data+ for
737
- # reading and/or writing. In addition to the CSV instance methods, several IO
738
- # methods are delegated. (See CSV::open() for a complete list.) If you pass
743
+ # reading and/or writing. In addition to the CSV instance methods, several IO
744
+ # methods are delegated. (See CSV::open() for a complete list.) If you pass
739
745
  # a String for +data+, you can later retrieve it (after writing to it, for
740
746
  # example) with CSV.string().
741
747
  #
742
748
  # Note that a wrapped String will be positioned at the beginning (for
743
- # reading). If you want it at the end (for writing), use CSV::generate().
749
+ # reading). If you want it at the end (for writing), use CSV::generate().
744
750
  # If you want any other positioning, pass a preset StringIO object instead.
745
751
  #
746
752
  # You may set any reading and/or writing preferences in the +options+ Hash.
@@ -750,25 +756,25 @@ class CSV
750
756
  # This String will be transcoded into
751
757
  # the data's Encoding before parsing.
752
758
  # <b><tt>:row_sep</tt></b>:: The String appended to the end of each
753
- # row. This can be set to the special
759
+ # row. This can be set to the special
754
760
  # <tt>:auto</tt> setting, which requests
755
761
  # that CSV automatically discover this
756
- # from the data. Auto-discovery reads
762
+ # from the data. Auto-discovery reads
757
763
  # ahead in the data looking for the next
758
764
  # <tt>"\r\n"</tt>, <tt>"\n"</tt>, or
759
- # <tt>"\r"</tt> sequence. A sequence
765
+ # <tt>"\r"</tt> sequence. A sequence
760
766
  # will be selected even if it occurs in
761
767
  # a quoted field, assuming that you
762
768
  # would have the same line endings
763
- # there. If none of those sequences is
769
+ # there. If none of those sequences is
764
770
  # found, +data+ is <tt>ARGF</tt>,
765
771
  # <tt>STDIN</tt>, <tt>STDOUT</tt>, or
766
772
  # <tt>STDERR</tt>, or the stream is only
767
773
  # available for output, the default
768
774
  # <tt>$INPUT_RECORD_SEPARATOR</tt>
769
- # (<tt>$/</tt>) is used. Obviously,
770
- # discovery takes a little time. Set
771
- # manually if speed is important. Also
775
+ # (<tt>$/</tt>) is used. Obviously,
776
+ # discovery takes a little time. Set
777
+ # manually if speed is important. Also
772
778
  # note that IO objects should be opened
773
779
  # in binary mode on Windows if this
774
780
  # feature will be used as the
@@ -780,7 +786,7 @@ class CSV
780
786
  # before parsing.
781
787
  # <b><tt>:quote_char</tt></b>:: The character used to quote fields.
782
788
  # This has to be a single character
783
- # String. This is useful for
789
+ # String. This is useful for
784
790
  # application that incorrectly use
785
791
  # <tt>'</tt> as the quote character
786
792
  # instead of the correct <tt>"</tt>.
@@ -791,21 +797,21 @@ class CSV
791
797
  # before parsing.
792
798
  # <b><tt>:field_size_limit</tt></b>:: This is a maximum size CSV will read
793
799
  # ahead looking for the closing quote
794
- # for a field. (In truth, it reads to
800
+ # for a field. (In truth, it reads to
795
801
  # the first line ending beyond this
796
- # size.) If a quote cannot be found
802
+ # size.) If a quote cannot be found
797
803
  # within the limit CSV will raise a
798
804
  # MalformedCSVError, assuming the data
799
- # is faulty. You can use this limit to
805
+ # is faulty. You can use this limit to
800
806
  # prevent what are effectively DoS
801
- # attacks on the parser. However, this
807
+ # attacks on the parser. However, this
802
808
  # limit can cause a legitimate parse to
803
809
  # fail and thus is set to +nil+, or off,
804
810
  # by default.
805
811
  # <b><tt>:converters</tt></b>:: An Array of names from the Converters
806
812
  # Hash and/or lambdas that handle custom
807
- # conversion. A single converter
808
- # doesn't have to be in an Array. All
813
+ # conversion. A single converter
814
+ # doesn't have to be in an Array. All
809
815
  # built-in converters try to transcode
810
816
  # fields to UTF-8 before converting.
811
817
  # The conversion will fail if the data
@@ -815,7 +821,7 @@ class CSV
815
821
  # unconverted_fields() method will be
816
822
  # added to all returned rows (Array or
817
823
  # CSV::Row) that will return the fields
818
- # as they were before conversion. Note
824
+ # as they were before conversion. Note
819
825
  # that <tt>:headers</tt> supplied by
820
826
  # Array or String were not fields of the
821
827
  # document and thus will have an empty
@@ -823,21 +829,21 @@ class CSV
823
829
  # <b><tt>:headers</tt></b>:: If set to <tt>:first_row</tt> or
824
830
  # +true+, the initial row of the CSV
825
831
  # file will be treated as a row of
826
- # headers. If set to an Array, the
832
+ # headers. If set to an Array, the
827
833
  # contents will be used as the headers.
828
834
  # If set to a String, the String is run
829
835
  # through a call of CSV::parse_line()
830
836
  # with the same <tt>:col_sep</tt>,
831
837
  # <tt>:row_sep</tt>, and
832
838
  # <tt>:quote_char</tt> as this instance
833
- # to produce an Array of headers. This
839
+ # to produce an Array of headers. This
834
840
  # setting causes CSV#shift() to return
835
841
  # rows as CSV::Row objects instead of
836
842
  # Arrays and CSV#read() to return
837
843
  # CSV::Table objects instead of an Array
838
844
  # of Arrays.
839
845
  # <b><tt>:return_headers</tt></b>:: When +false+, header rows are silently
840
- # swallowed. If set to +true+, header
846
+ # swallowed. If set to +true+, header
841
847
  # rows are returned in a CSV::Row object
842
848
  # with identical headers and
843
849
  # fields (save that the fields do not go
@@ -848,12 +854,12 @@ class CSV
848
854
  # <b><tt>:header_converters</tt></b>:: Identical in functionality to
849
855
  # <tt>:converters</tt> save that the
850
856
  # conversions are only made to header
851
- # rows. All built-in converters try to
857
+ # rows. All built-in converters try to
852
858
  # transcode headers to UTF-8 before
853
- # converting. The conversion will fail
859
+ # converting. The conversion will fail
854
860
  # if the data cannot be transcoded,
855
861
  # leaving the header unchanged.
856
- # <b><tt>:skip_blanks</tt></b>:: When set to a +true+ value, CSV will
862
+ # <b><tt>:skip_blanks</tt></b>:: When setting a +true+ value, CSV will
857
863
  # skip over any empty rows. Note that
858
864
  # this setting will not skip rows that
859
865
  # contain column separators, even if
@@ -863,9 +869,9 @@ class CSV
863
869
  # using <tt>:skip_lines</tt>, or
864
870
  # inspecting fields.compact.empty? on
865
871
  # each row.
866
- # <b><tt>:force_quotes</tt></b>:: When set to a +true+ value, CSV will
872
+ # <b><tt>:force_quotes</tt></b>:: When setting a +true+ value, CSV will
867
873
  # quote all CSV fields it creates.
868
- # <b><tt>:skip_lines</tt></b>:: When set to an object responding to
874
+ # <b><tt>:skip_lines</tt></b>:: When setting an object responding to
869
875
  # <tt>match</tt>, every line matching
870
876
  # it is considered a comment and ignored
871
877
  # during parsing. When set to a String,
@@ -874,17 +880,17 @@ class CSV
874
880
  # a comment. If the passed object does
875
881
  # not respond to <tt>match</tt>,
876
882
  # <tt>ArgumentError</tt> is thrown.
877
- # <b><tt>:liberal_parsing</tt></b>:: When set to a +true+ value, CSV will
883
+ # <b><tt>:liberal_parsing</tt></b>:: When setting a +true+ value, CSV will
878
884
  # attempt to parse input not conformant
879
885
  # with RFC 4180, such as double quotes
880
886
  # in unquoted fields.
881
887
  # <b><tt>:nil_value</tt></b>:: When set an object, any values of an
882
- # empty field are replaced by the set
888
+ # empty field is replaced by the set
883
889
  # object, not nil.
884
- # <b><tt>:empty_value</tt></b>:: When set an object, any values of a
890
+ # <b><tt>:empty_value</tt></b>:: When setting an object, any values of a
885
891
  # blank string field is replaced by
886
892
  # the set object.
887
- # <b><tt>:quote_empty</tt></b>:: When set to a +true+ value, CSV will
893
+ # <b><tt>:quote_empty</tt></b>:: When setting a +true+ value, CSV will
888
894
  # quote empty values with double quotes.
889
895
  # When +false+, CSV will emit an
890
896
  # empty string for an empty field value.
@@ -901,11 +907,11 @@ class CSV
901
907
  # <b><tt>:write_empty_value</tt></b>:: When a <tt>String</tt> or +nil+ value,
902
908
  # empty value(s) on each line will be
903
909
  # replaced with the specified value.
904
- # <b><tt>:strip</tt></b>:: When set to a +true+ value, CSV will
910
+ # <b><tt>:strip</tt></b>:: When setting a +true+ value, CSV will
905
911
  # strip "\t\r\n\f\v" around the values.
906
912
  # If you specify a string instead of
907
913
  # +true+, CSV will strip string. The
908
- # length of string must be 1.
914
+ # length of the string must be 1.
909
915
  #
910
916
  # See CSV::DEFAULT_OPTIONS for the default settings.
911
917
  #
@@ -939,8 +945,12 @@ class CSV
939
945
  strip: false)
940
946
  raise ArgumentError.new("Cannot parse nil as CSV") if data.nil?
941
947
 
942
- # create the IO object we will read from
943
- @io = data.is_a?(String) ? StringIO.new(data) : data
948
+ if data.is_a?(String)
949
+ @io = StringIO.new(data)
950
+ @io.set_encoding(encoding || data.encoding)
951
+ else
952
+ @io = data
953
+ end
944
954
  @encoding = determine_encoding(encoding, internal_encoding)
945
955
 
946
956
  @base_fields_converter_options = {
@@ -992,41 +1002,47 @@ class CSV
992
1002
  end
993
1003
 
994
1004
  #
995
- # The encoded <tt>:col_sep</tt> used in parsing and writing. See CSV::new
996
- # for details.
1005
+ # The encoded <tt>:col_sep</tt> used in parsing and writing.
1006
+ # See CSV::new for details.
997
1007
  #
998
1008
  def col_sep
999
1009
  parser.column_separator
1000
1010
  end
1001
1011
 
1002
1012
  #
1003
- # The encoded <tt>:row_sep</tt> used in parsing and writing. See CSV::new
1004
- # for details.
1013
+ # The encoded <tt>:row_sep</tt> used in parsing and writing.
1014
+ # See CSV::new for details.
1005
1015
  #
1006
1016
  def row_sep
1007
1017
  parser.row_separator
1008
1018
  end
1009
1019
 
1010
1020
  #
1011
- # The encoded <tt>:quote_char</tt> used in parsing and writing. See CSV::new
1012
- # for details.
1021
+ # The encoded <tt>:quote_char</tt> used in parsing and writing.
1022
+ # See CSV::new for details.
1013
1023
  #
1014
1024
  def quote_char
1015
1025
  parser.quote_character
1016
1026
  end
1017
1027
 
1018
- # The limit for field size, if any. See CSV::new for details.
1028
+ #
1029
+ # The limit for field size, if any.
1030
+ # See CSV::new for details.
1031
+ #
1019
1032
  def field_size_limit
1020
1033
  parser.field_size_limit
1021
1034
  end
1022
1035
 
1023
- # The regex marking a line as a comment. See CSV::new for details
1036
+ #
1037
+ # The regex marking a line as a comment.
1038
+ # See CSV::new for details.
1039
+ #
1024
1040
  def skip_lines
1025
1041
  parser.skip_lines
1026
1042
  end
1027
1043
 
1028
1044
  #
1029
- # Returns the current list of converters in effect. See CSV::new for details.
1045
+ # Returns the current list of converters in effect. See CSV::new for details.
1030
1046
  # Built-in converters will be returned by name, while others will be returned
1031
1047
  # as is.
1032
1048
  #
@@ -1036,9 +1052,10 @@ class CSV
1036
1052
  name ? name.first : converter
1037
1053
  end
1038
1054
  end
1055
+
1039
1056
  #
1040
- # Returns +true+ if unconverted_fields() to parsed results. See CSV::new
1041
- # for details.
1057
+ # Returns +true+ if unconverted_fields() to parsed results.
1058
+ # See CSV::new for details.
1042
1059
  #
1043
1060
  def unconverted_fields?
1044
1061
  parser.unconverted_fields?
@@ -1046,8 +1063,8 @@ class CSV
1046
1063
 
1047
1064
  #
1048
1065
  # Returns +nil+ if headers will not be used, +true+ if they will but have not
1049
- # yet been read, or the actual headers after they have been read. See
1050
- # CSV::new for details.
1066
+ # yet been read, or the actual headers after they have been read.
1067
+ # See CSV::new for details.
1051
1068
  #
1052
1069
  def headers
1053
1070
  if @writer
@@ -1068,14 +1085,17 @@ class CSV
1068
1085
  parser.return_headers?
1069
1086
  end
1070
1087
 
1071
- # Returns +true+ if headers are written in output. See CSV::new for details.
1088
+ #
1089
+ # Returns +true+ if headers are written in output.
1090
+ # See CSV::new for details.
1091
+ #
1072
1092
  def write_headers?
1073
1093
  @writer_options[:write_headers]
1074
1094
  end
1075
1095
 
1076
1096
  #
1077
- # Returns the current list of converters in effect for headers. See CSV::new
1078
- # for details. Built-in converters will be returned by name, while others
1097
+ # Returns the current list of converters in effect for headers. See CSV::new
1098
+ # for details. Built-in converters will be returned by name, while others
1079
1099
  # will be returned as is.
1080
1100
  #
1081
1101
  def header_converters
@@ -1201,7 +1221,7 @@ class CSV
1201
1221
 
1202
1222
  #
1203
1223
  # The primary write method for wrapped Strings and IOs, +row+ (an Array or
1204
- # CSV::Row) is converted to CSV and appended to the data source. When a
1224
+ # CSV::Row) is converted to CSV and appended to the data source. When a
1205
1225
  # CSV::Row is passed, only the row's fields() are appended to the output.
1206
1226
  #
1207
1227
  # The data source must be open for writing.
@@ -1223,9 +1243,9 @@ class CSV
1223
1243
  # block that handles a custom conversion.
1224
1244
  #
1225
1245
  # If you provide a block that takes one argument, it will be passed the field
1226
- # and is expected to return the converted value or the field itself. If your
1246
+ # and is expected to return the converted value or the field itself. If your
1227
1247
  # block takes two arguments, it will also be passed a CSV::FieldInfo Struct,
1228
- # containing details about the field. Again, the block should return a
1248
+ # containing details about the field. Again, the block should return a
1229
1249
  # converted field or the field itself.
1230
1250
  #
1231
1251
  def convert(name = nil, &converter)
@@ -1377,9 +1397,9 @@ class CSV
1377
1397
 
1378
1398
  #
1379
1399
  # Processes +fields+ with <tt>@converters</tt>, or <tt>@header_converters</tt>
1380
- # if +headers+ is passed as +true+, returning the converted field set. Any
1400
+ # if +headers+ is passed as +true+, returning the converted field set. Any
1381
1401
  # converter that changes the field into something other than a String halts
1382
- # the pipeline of conversion for that field. This is primarily an efficiency
1402
+ # the pipeline of conversion for that field. This is primarily an efficiency
1383
1403
  # shortcut.
1384
1404
  #
1385
1405
  def convert_fields(fields, headers = false)