csv 3.1.6 → 3.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/NEWS.md +20 -0
- data/doc/{arguments → csv/arguments}/io.rdoc +0 -0
- data/doc/{options → csv/options}/common/col_sep.rdoc +0 -0
- data/doc/{options → csv/options}/common/quote_char.rdoc +0 -0
- data/doc/{options → csv/options}/common/row_sep.rdoc +0 -0
- data/doc/{options → csv/options}/generating/force_quotes.rdoc +0 -0
- data/doc/{options → csv/options}/generating/quote_empty.rdoc +0 -0
- data/doc/{options → csv/options}/generating/write_converters.rdoc +0 -0
- data/doc/{options → csv/options}/generating/write_empty_value.rdoc +0 -0
- data/doc/{options → csv/options}/generating/write_headers.rdoc +0 -0
- data/doc/{options → csv/options}/generating/write_nil_value.rdoc +0 -0
- data/doc/{options → csv/options}/parsing/converters.rdoc +0 -0
- data/doc/{options → csv/options}/parsing/empty_value.rdoc +0 -0
- data/doc/{options → csv/options}/parsing/field_size_limit.rdoc +0 -0
- data/doc/{options → csv/options}/parsing/header_converters.rdoc +0 -0
- data/doc/{options → csv/options}/parsing/headers.rdoc +0 -0
- data/doc/{options → csv/options}/parsing/liberal_parsing.rdoc +0 -0
- data/doc/{options → csv/options}/parsing/nil_value.rdoc +0 -0
- data/doc/{options → csv/options}/parsing/return_headers.rdoc +0 -0
- data/doc/{options → csv/options}/parsing/skip_blanks.rdoc +0 -0
- data/doc/{options → csv/options}/parsing/skip_lines.rdoc +0 -0
- data/doc/{options → csv/options}/parsing/strip.rdoc +0 -0
- data/doc/{options → csv/options}/parsing/unconverted_fields.rdoc +0 -0
- data/lib/csv.rb +142 -46
- data/lib/csv/table.rb +285 -64
- data/lib/csv/version.rb +1 -1
- metadata +26 -40
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c834580f6d364830ddcd85b07edcb44fc91520fd594492a835cb57f43f145c94
|
4
|
+
data.tar.gz: 989310760b22148eeb70be9181a39c2d08c8040f7e79fd6a06dc7586409c4e7f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 75859dd4eff126ab15bf372305da6eeb638ce1927186931f3ea87fe00c0a769c8adb38cb786b8ee3f7fd418de720d26fe01fba9ca28ac565bbd761431057cec8
|
7
|
+
data.tar.gz: 56b5de70961f3e9792296e6b68941fa1ea1e1eaa5ad2811ae47954a775c986d8f9455af50e5e6d25deb797794b697cef0e0c4a87695dc3a42d9fa477008d85dc
|
data/NEWS.md
CHANGED
@@ -1,5 +1,25 @@
|
|
1
1
|
# News
|
2
2
|
|
3
|
+
## 3.1.7 - 2020-08-04
|
4
|
+
|
5
|
+
### Improvements
|
6
|
+
|
7
|
+
* Improved document.
|
8
|
+
[GitHub#158][GitHub#160][GitHub#161]
|
9
|
+
[Patch by Burdette Lamar]
|
10
|
+
|
11
|
+
* Updated required Ruby version to 2.5.0 or later.
|
12
|
+
[GitHub#159]
|
13
|
+
[Patch by Gabriel Nagy]
|
14
|
+
|
15
|
+
* Removed stringio 0.1.3 or later dependency.
|
16
|
+
|
17
|
+
### Thanks
|
18
|
+
|
19
|
+
* Burdette Lamar
|
20
|
+
|
21
|
+
* Gabriel Nagy
|
22
|
+
|
3
23
|
## 3.1.6 - 2020-07-20
|
4
24
|
|
5
25
|
### Improvements
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
data/lib/csv.rb
CHANGED
@@ -104,7 +104,7 @@ require_relative "csv/writer"
|
|
104
104
|
using CSV::MatchP if CSV.const_defined?(:MatchP)
|
105
105
|
|
106
106
|
# == \CSV
|
107
|
-
# \CSV (comma-separated
|
107
|
+
# \CSV (comma-separated values) data is a text representation of a table:
|
108
108
|
# - A _row_ _separator_ delimits table rows.
|
109
109
|
# A common row separator is the newline character <tt>"\n"</tt>.
|
110
110
|
# - A _column_ _separator_ delimits fields in a row.
|
@@ -357,35 +357,35 @@ using CSV::MatchP if CSV.const_defined?(:MatchP)
|
|
357
357
|
# - +nil_value+: Specifies the object that is to be substituted for each null (no-text) field.
|
358
358
|
# - +empty_value+: Specifies the object that is to be substituted for each empty field.
|
359
359
|
#
|
360
|
-
# :include: ../doc/options/common/row_sep.rdoc
|
360
|
+
# :include: ../doc/csv/options/common/row_sep.rdoc
|
361
361
|
#
|
362
|
-
# :include: ../doc/options/common/col_sep.rdoc
|
362
|
+
# :include: ../doc/csv/options/common/col_sep.rdoc
|
363
363
|
#
|
364
|
-
# :include: ../doc/options/common/quote_char.rdoc
|
364
|
+
# :include: ../doc/csv/options/common/quote_char.rdoc
|
365
365
|
#
|
366
|
-
# :include: ../doc/options/parsing/field_size_limit.rdoc
|
366
|
+
# :include: ../doc/csv/options/parsing/field_size_limit.rdoc
|
367
367
|
#
|
368
|
-
# :include: ../doc/options/parsing/converters.rdoc
|
368
|
+
# :include: ../doc/csv/options/parsing/converters.rdoc
|
369
369
|
#
|
370
|
-
# :include: ../doc/options/parsing/unconverted_fields.rdoc
|
370
|
+
# :include: ../doc/csv/options/parsing/unconverted_fields.rdoc
|
371
371
|
#
|
372
|
-
# :include: ../doc/options/parsing/headers.rdoc
|
372
|
+
# :include: ../doc/csv/options/parsing/headers.rdoc
|
373
373
|
#
|
374
|
-
# :include: ../doc/options/parsing/return_headers.rdoc
|
374
|
+
# :include: ../doc/csv/options/parsing/return_headers.rdoc
|
375
375
|
#
|
376
|
-
# :include: ../doc/options/parsing/header_converters.rdoc
|
376
|
+
# :include: ../doc/csv/options/parsing/header_converters.rdoc
|
377
377
|
#
|
378
|
-
# :include: ../doc/options/parsing/skip_blanks.rdoc
|
378
|
+
# :include: ../doc/csv/options/parsing/skip_blanks.rdoc
|
379
379
|
#
|
380
|
-
# :include: ../doc/options/parsing/skip_lines.rdoc
|
380
|
+
# :include: ../doc/csv/options/parsing/skip_lines.rdoc
|
381
381
|
#
|
382
|
-
# :include: ../doc/options/parsing/strip.rdoc
|
382
|
+
# :include: ../doc/csv/options/parsing/strip.rdoc
|
383
383
|
#
|
384
|
-
# :include: ../doc/options/parsing/liberal_parsing.rdoc
|
384
|
+
# :include: ../doc/csv/options/parsing/liberal_parsing.rdoc
|
385
385
|
#
|
386
|
-
# :include: ../doc/options/parsing/nil_value.rdoc
|
386
|
+
# :include: ../doc/csv/options/parsing/nil_value.rdoc
|
387
387
|
#
|
388
|
-
# :include: ../doc/options/parsing/empty_value.rdoc
|
388
|
+
# :include: ../doc/csv/options/parsing/empty_value.rdoc
|
389
389
|
#
|
390
390
|
# ==== Options for Generating
|
391
391
|
#
|
@@ -400,23 +400,23 @@ using CSV::MatchP if CSV.const_defined?(:MatchP)
|
|
400
400
|
# - +write_nil_value+: Specifies the object that is to be substituted for each +nil+-valued field.
|
401
401
|
# - +write_empty_value+: Specifies the object that is to be substituted for each empty field.
|
402
402
|
#
|
403
|
-
# :include: ../doc/options/common/row_sep.rdoc
|
403
|
+
# :include: ../doc/csv/options/common/row_sep.rdoc
|
404
404
|
#
|
405
|
-
# :include: ../doc/options/common/col_sep.rdoc
|
405
|
+
# :include: ../doc/csv/options/common/col_sep.rdoc
|
406
406
|
#
|
407
|
-
# :include: ../doc/options/common/quote_char.rdoc
|
407
|
+
# :include: ../doc/csv/options/common/quote_char.rdoc
|
408
408
|
#
|
409
|
-
# :include: ../doc/options/generating/write_headers.rdoc
|
409
|
+
# :include: ../doc/csv/options/generating/write_headers.rdoc
|
410
410
|
#
|
411
|
-
# :include: ../doc/options/generating/force_quotes.rdoc
|
411
|
+
# :include: ../doc/csv/options/generating/force_quotes.rdoc
|
412
412
|
#
|
413
|
-
# :include: ../doc/options/generating/quote_empty.rdoc
|
413
|
+
# :include: ../doc/csv/options/generating/quote_empty.rdoc
|
414
414
|
#
|
415
|
-
# :include: ../doc/options/generating/write_converters.rdoc
|
415
|
+
# :include: ../doc/csv/options/generating/write_converters.rdoc
|
416
416
|
#
|
417
|
-
# :include: ../doc/options/generating/write_nil_value.rdoc
|
417
|
+
# :include: ../doc/csv/options/generating/write_nil_value.rdoc
|
418
418
|
#
|
419
|
-
# :include: ../doc/options/generating/write_empty_value.rdoc
|
419
|
+
# :include: ../doc/csv/options/generating/write_empty_value.rdoc
|
420
420
|
#
|
421
421
|
# === \CSV with Headers
|
422
422
|
#
|
@@ -1075,7 +1075,7 @@ class CSV
|
|
1075
1075
|
# Calls the block with each row read from source +path+ or +io+.
|
1076
1076
|
#
|
1077
1077
|
# * Argument +path+, if given, must be the path to a file.
|
1078
|
-
# :include: ../doc/arguments/io.rdoc
|
1078
|
+
# :include: ../doc/csv/arguments/io.rdoc
|
1079
1079
|
# * Argument +mode+, if given, must be a \File mode
|
1080
1080
|
# See {Open Mode}[IO.html#method-c-new-label-Open+Mode].
|
1081
1081
|
# * Arguments <tt>**options</tt> must be keyword options.
|
@@ -1322,7 +1322,7 @@ class CSV
|
|
1322
1322
|
# :replace => string # replacement string ("?" or "\uFFFD" if not specified)
|
1323
1323
|
#
|
1324
1324
|
# * Argument +path+, if given, must be the path to a file.
|
1325
|
-
# :include: ../doc/arguments/io.rdoc
|
1325
|
+
# :include: ../doc/csv/arguments/io.rdoc
|
1326
1326
|
# * Argument +mode+, if given, must be a \File mode
|
1327
1327
|
# See {Open Mode}[IO.html#method-c-new-label-Open+Mode].
|
1328
1328
|
# * Arguments <tt>**options</tt> must be keyword options.
|
@@ -1427,7 +1427,7 @@ class CSV
|
|
1427
1427
|
#
|
1428
1428
|
# - Argument +string+ should be a \String object;
|
1429
1429
|
# it will be put into a new StringIO object positioned at the beginning.
|
1430
|
-
# :include: ../doc/arguments/io.rdoc
|
1430
|
+
# :include: ../doc/csv/arguments/io.rdoc
|
1431
1431
|
# - Argument +options+: see {Options for Parsing}[#class-CSV-label-Options+for+Parsing]
|
1432
1432
|
#
|
1433
1433
|
# ====== Without Option +headers+
|
@@ -1552,7 +1552,7 @@ class CSV
|
|
1552
1552
|
#
|
1553
1553
|
# - Argument +string+ should be a \String object;
|
1554
1554
|
# it will be put into a new StringIO object positioned at the beginning.
|
1555
|
-
# :include: ../doc/arguments/io.rdoc
|
1555
|
+
# :include: ../doc/csv/arguments/io.rdoc
|
1556
1556
|
# - Argument +options+: see {Options for Parsing}[#class-CSV-label-Options+for+Parsing]
|
1557
1557
|
#
|
1558
1558
|
# ====== Without Option +headers+
|
@@ -1672,7 +1672,7 @@ class CSV
|
|
1672
1672
|
#
|
1673
1673
|
# - Argument +string+ should be a \String object;
|
1674
1674
|
# it will be put into a new StringIO object positioned at the beginning.
|
1675
|
-
# :include: ../doc/arguments/io.rdoc
|
1675
|
+
# :include: ../doc/csv/arguments/io.rdoc
|
1676
1676
|
# - Argument +options+: See:
|
1677
1677
|
# * {Options for Parsing}[#class-CSV-label-Options+for+Parsing]
|
1678
1678
|
# * {Options for Generating}[#class-CSV-label-Options+for+Generating]
|
@@ -2080,7 +2080,7 @@ class CSV
|
|
2080
2080
|
### End Delegation ###
|
2081
2081
|
|
2082
2082
|
# :call-seq:
|
2083
|
-
# csv
|
2083
|
+
# csv << row -> self
|
2084
2084
|
#
|
2085
2085
|
# Appends a row to +self+.
|
2086
2086
|
#
|
@@ -2120,7 +2120,7 @@ class CSV
|
|
2120
2120
|
# csv << :foo
|
2121
2121
|
# end
|
2122
2122
|
#
|
2123
|
-
# Raises an exception if the output stream is not
|
2123
|
+
# Raises an exception if the output stream is not opened for writing:
|
2124
2124
|
# path = 't.csv'
|
2125
2125
|
# File.write(path, '')
|
2126
2126
|
# File.open(path) do |file|
|
@@ -2272,25 +2272,57 @@ class CSV
|
|
2272
2272
|
|
2273
2273
|
include Enumerable
|
2274
2274
|
|
2275
|
+
# :call-seq:
|
2276
|
+
# csv.each -> enumerator
|
2277
|
+
# csv.each {|row| ...}
|
2275
2278
|
#
|
2276
|
-
#
|
2279
|
+
# Calls the block with each successive row.
|
2280
|
+
# The data source must be opened for reading.
|
2277
2281
|
#
|
2278
|
-
#
|
2282
|
+
# Without headers:
|
2283
|
+
# string = "foo,0\nbar,1\nbaz,2\n"
|
2284
|
+
# csv = CSV.new(string)
|
2285
|
+
# csv.each do |row|
|
2286
|
+
# p row
|
2287
|
+
# end
|
2288
|
+
# Output:
|
2289
|
+
# ["foo", "0"]
|
2290
|
+
# ["bar", "1"]
|
2291
|
+
# ["baz", "2"]
|
2279
2292
|
#
|
2280
|
-
#
|
2293
|
+
# With headers:
|
2294
|
+
# string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
|
2295
|
+
# csv = CSV.new(string, headers: true)
|
2296
|
+
# csv.each do |row|
|
2297
|
+
# p row
|
2298
|
+
# end
|
2299
|
+
# Output:
|
2300
|
+
# <CSV::Row "Name":"foo" "Value":"0">
|
2301
|
+
# <CSV::Row "Name":"bar" "Value":"1">
|
2302
|
+
# <CSV::Row "Name":"baz" "Value":"2">
|
2303
|
+
#
|
2304
|
+
# ---
|
2281
2305
|
#
|
2306
|
+
# Raises an exception if the source is not opened for reading:
|
2307
|
+
# string = "foo,0\nbar,1\nbaz,2\n"
|
2308
|
+
# csv = CSV.new(string)
|
2309
|
+
# csv.close
|
2310
|
+
# # Raises IOError (not opened for reading)
|
2311
|
+
# csv.each do |row|
|
2312
|
+
# p row
|
2313
|
+
# end
|
2282
2314
|
def each(&block)
|
2283
2315
|
parser_enumerator.each(&block)
|
2284
2316
|
end
|
2285
2317
|
|
2286
2318
|
# :call-seq:
|
2287
|
-
#
|
2319
|
+
# csv.read -> array or csv_table
|
2288
2320
|
#
|
2289
2321
|
# Forms the remaining rows from +self+ into:
|
2290
2322
|
# - A CSV::Table object, if headers are in use.
|
2291
|
-
# - An Array of Arrays, otherwise.
|
2323
|
+
# - An \Array of Arrays, otherwise.
|
2292
2324
|
#
|
2293
|
-
# The data source must be
|
2325
|
+
# The data source must be opened for reading.
|
2294
2326
|
#
|
2295
2327
|
# Without headers:
|
2296
2328
|
# string = "foo,0\nbar,1\nbaz,2\n"
|
@@ -2305,6 +2337,15 @@ class CSV
|
|
2305
2337
|
# File.write(path, string)
|
2306
2338
|
# csv = CSV.open(path, headers: true)
|
2307
2339
|
# csv.read # => #<CSV::Table mode:col_or_row row_count:4>
|
2340
|
+
#
|
2341
|
+
# ---
|
2342
|
+
#
|
2343
|
+
# Raises an exception if the source is not opened for reading:
|
2344
|
+
# string = "foo,0\nbar,1\nbaz,2\n"
|
2345
|
+
# csv = CSV.new(string)
|
2346
|
+
# csv.close
|
2347
|
+
# # Raises IOError (not opened for reading)
|
2348
|
+
# csv.read
|
2308
2349
|
def read
|
2309
2350
|
rows = to_a
|
2310
2351
|
if parser.use_headers?
|
@@ -2315,18 +2356,69 @@ class CSV
|
|
2315
2356
|
end
|
2316
2357
|
alias_method :readlines, :read
|
2317
2358
|
|
2318
|
-
#
|
2359
|
+
# :call-seq:
|
2360
|
+
# csv.header_row? -> true or false
|
2361
|
+
#
|
2362
|
+
# Returns +true+ if the next row to be read is a header row\;
|
2363
|
+
# +false+ otherwise.
|
2364
|
+
#
|
2365
|
+
# Without headers:
|
2366
|
+
# string = "foo,0\nbar,1\nbaz,2\n"
|
2367
|
+
# csv = CSV.new(string)
|
2368
|
+
# csv.header_row? # => false
|
2369
|
+
#
|
2370
|
+
# With headers:
|
2371
|
+
# string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
|
2372
|
+
# csv = CSV.new(string, headers: true)
|
2373
|
+
# csv.header_row? # => true
|
2374
|
+
# csv.shift # => #<CSV::Row "Name":"foo" "Value":"0">
|
2375
|
+
# csv.header_row? # => false
|
2376
|
+
#
|
2377
|
+
# ---
|
2378
|
+
#
|
2379
|
+
# Raises an exception if the source is not opened for reading:
|
2380
|
+
# string = "foo,0\nbar,1\nbaz,2\n"
|
2381
|
+
# csv = CSV.new(string)
|
2382
|
+
# csv.close
|
2383
|
+
# # Raises IOError (not opened for reading)
|
2384
|
+
# csv.header_row?
|
2319
2385
|
def header_row?
|
2320
2386
|
parser.header_row?
|
2321
2387
|
end
|
2322
2388
|
|
2389
|
+
# :call-seq:
|
2390
|
+
# csv.shift -> array, csv_row, or nil
|
2323
2391
|
#
|
2324
|
-
#
|
2325
|
-
#
|
2326
|
-
#
|
2392
|
+
# Returns the next row of data as:
|
2393
|
+
# - An \Array if no headers are used.
|
2394
|
+
# - A CSV::Row object if headers are used.
|
2327
2395
|
#
|
2328
|
-
# The data source must be
|
2396
|
+
# The data source must be opened for reading.
|
2329
2397
|
#
|
2398
|
+
# Without headers:
|
2399
|
+
# string = "foo,0\nbar,1\nbaz,2\n"
|
2400
|
+
# csv = CSV.new(string)
|
2401
|
+
# csv.shift # => ["foo", "0"]
|
2402
|
+
# csv.shift # => ["bar", "1"]
|
2403
|
+
# csv.shift # => ["baz", "2"]
|
2404
|
+
# csv.shift # => nil
|
2405
|
+
#
|
2406
|
+
# With headers:
|
2407
|
+
# string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
|
2408
|
+
# csv = CSV.new(string, headers: true)
|
2409
|
+
# csv.shift # => #<CSV::Row "Name":"foo" "Value":"0">
|
2410
|
+
# csv.shift # => #<CSV::Row "Name":"bar" "Value":"1">
|
2411
|
+
# csv.shift # => #<CSV::Row "Name":"baz" "Value":"2">
|
2412
|
+
# csv.shift # => nil
|
2413
|
+
#
|
2414
|
+
# ---
|
2415
|
+
#
|
2416
|
+
# Raises an exception if the source is not opened for reading:
|
2417
|
+
# string = "foo,0\nbar,1\nbaz,2\n"
|
2418
|
+
# csv = CSV.new(string)
|
2419
|
+
# csv.close
|
2420
|
+
# # Raises IOError (not opened for reading)
|
2421
|
+
# csv.shift
|
2330
2422
|
def shift
|
2331
2423
|
if @eof_error
|
2332
2424
|
eof_error, @eof_error = @eof_error, nil
|
@@ -2341,10 +2433,14 @@ class CSV
|
|
2341
2433
|
alias_method :gets, :shift
|
2342
2434
|
alias_method :readline, :shift
|
2343
2435
|
|
2436
|
+
# :call-seq:
|
2437
|
+
# csv.inspect -> string
|
2344
2438
|
#
|
2345
|
-
# Returns a
|
2346
|
-
#
|
2347
|
-
#
|
2439
|
+
# Returns a \String showing certain properties of +self+:
|
2440
|
+
# string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
|
2441
|
+
# csv = CSV.new(string, headers: true)
|
2442
|
+
# s = csv.inspect
|
2443
|
+
# s # => "#<CSV io_type:StringIO encoding:UTF-8 lineno:0 col_sep:\",\" row_sep:\"\\n\" quote_char:\"\\\"\" headers:true>"
|
2348
2444
|
def inspect
|
2349
2445
|
str = ["#<", self.class.to_s, " io_type:"]
|
2350
2446
|
# show type of wrapped IO
|
data/lib/csv/table.rb
CHANGED
@@ -3,31 +3,199 @@
|
|
3
3
|
require "forwardable"
|
4
4
|
|
5
5
|
class CSV
|
6
|
+
# = \CSV::Table
|
7
|
+
# A \CSV::Table instance is an object representing \CSV data.
|
8
|
+
# (see {class CSV}[../CSV.html]).
|
6
9
|
#
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
10
|
+
# The instance may have:
|
11
|
+
# - Rows: each is a Table::Row object.
|
12
|
+
# - Headers: names for the columns.
|
10
13
|
#
|
11
|
-
#
|
12
|
-
# row processing is activated.
|
14
|
+
# === Instance Methods
|
13
15
|
#
|
16
|
+
# \CSV::Table has three groups of instance methods:
|
17
|
+
# - Its own internally defined instance methods.
|
18
|
+
# - Methods included by module Enumerable.
|
19
|
+
# - Methods delegated to class Array.:
|
20
|
+
# * Array#empty?
|
21
|
+
# * Array#length
|
22
|
+
# * Array#size
|
23
|
+
#
|
24
|
+
# == Creating a \CSV::Table Instance
|
25
|
+
#
|
26
|
+
# Commonly, a new \CSV::Table instance is created by parsing \CSV source
|
27
|
+
# using headers:
|
28
|
+
# source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
|
29
|
+
# table = CSV.parse(source, headers: true)
|
30
|
+
# table.class # => CSV::Table
|
31
|
+
#
|
32
|
+
# You can also create an instance directly. See ::new.
|
33
|
+
#
|
34
|
+
# == Headers
|
35
|
+
#
|
36
|
+
# If a table has headers, the headers serve as labels for the columns of data.
|
37
|
+
# Each header serves as the label for its column.
|
38
|
+
#
|
39
|
+
# The headers for a \CSV::Table object are stored as an \Array of Strings.
|
40
|
+
#
|
41
|
+
# Commonly, headers are defined in the first row of \CSV source:
|
42
|
+
# source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
|
43
|
+
# table = CSV.parse(source, headers: true)
|
44
|
+
# table.headers # => ["Name", "Value"]
|
45
|
+
#
|
46
|
+
# If no headers are defined, the \Array is empty:
|
47
|
+
# table = CSV::Table.new([])
|
48
|
+
# table.headers # => []
|
49
|
+
#
|
50
|
+
# == Access Modes
|
51
|
+
#
|
52
|
+
# \CSV::Table provides three modes for accessing table data:
|
53
|
+
# - \Row mode.
|
54
|
+
# - Column mode.
|
55
|
+
# - Mixed mode (the default for a new table).
|
56
|
+
#
|
57
|
+
# The access mode for a\CSV::Table instance affects the behavior
|
58
|
+
# of some of its instance methods:
|
59
|
+
# - #[]
|
60
|
+
# - #[]=
|
61
|
+
# - #delete
|
62
|
+
# - #delete_if
|
63
|
+
# - #each
|
64
|
+
# - #values_at
|
65
|
+
#
|
66
|
+
# === \Row Mode
|
67
|
+
#
|
68
|
+
# Set a table to row mode with method #by_row!:
|
69
|
+
# source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
|
70
|
+
# table = CSV.parse(source, headers: true)
|
71
|
+
# table.by_row! # => #<CSV::Table mode:row row_count:4>
|
72
|
+
#
|
73
|
+
# Specify a single row by an \Integer index:
|
74
|
+
# # Get a row.
|
75
|
+
# table[1] # => #<CSV::Row "Name":"bar" "Value":"1">
|
76
|
+
# # Set a row, then get it.
|
77
|
+
# table[1] = CSV::Row.new(['Name', 'Value'], ['bam', 3])
|
78
|
+
# table[1] # => #<CSV::Row "Name":"bam" "Value":3>
|
79
|
+
#
|
80
|
+
# Specify a sequence of rows by a \Range:
|
81
|
+
# # Get rows.
|
82
|
+
# table[1..2] # => [#<CSV::Row "Name":"bam" "Value":3>, #<CSV::Row "Name":"baz" "Value":"2">]
|
83
|
+
# # Set rows, then get them.
|
84
|
+
# table[1..2] = [
|
85
|
+
# CSV::Row.new(['Name', 'Value'], ['bat', 4]),
|
86
|
+
# CSV::Row.new(['Name', 'Value'], ['bad', 5]),
|
87
|
+
# ]
|
88
|
+
# table[1..2] # => [["Name", #<CSV::Row "Name":"bat" "Value":4>], ["Value", #<CSV::Row "Name":"bad" "Value":5>]]
|
89
|
+
#
|
90
|
+
# === Column Mode
|
91
|
+
#
|
92
|
+
# Set a table to column mode with method #by_col!:
|
93
|
+
# source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
|
94
|
+
# table = CSV.parse(source, headers: true)
|
95
|
+
# table.by_col! # => #<CSV::Table mode:col row_count:4>
|
96
|
+
#
|
97
|
+
# Specify a column by an \Integer index:
|
98
|
+
# # Get a column.
|
99
|
+
# table[0]
|
100
|
+
# # Set a column, then get it.
|
101
|
+
# table[0] = ['FOO', 'BAR', 'BAZ']
|
102
|
+
# table[0] # => ["FOO", "BAR", "BAZ"]
|
103
|
+
#
|
104
|
+
# Specify a column by its \String header:
|
105
|
+
# # Get a column.
|
106
|
+
# table['Name'] # => ["FOO", "BAR", "BAZ"]
|
107
|
+
# # Set a column, then get it.
|
108
|
+
# table['Name'] = ['Foo', 'Bar', 'Baz']
|
109
|
+
# table['Name'] # => ["Foo", "Bar", "Baz"]
|
110
|
+
#
|
111
|
+
# === Mixed Mode
|
112
|
+
#
|
113
|
+
# In mixed mode, you can refer to either rows or columns:
|
114
|
+
# - An \Integer index refers to a row.
|
115
|
+
# - A \Range index refers to multiple rows.
|
116
|
+
# - A \String index refers to a column.
|
117
|
+
#
|
118
|
+
# Set a table to mixed mode with method #by_col_or_row!:
|
119
|
+
# source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
|
120
|
+
# table = CSV.parse(source, headers: true)
|
121
|
+
# table.by_col_or_row! # => #<CSV::Table mode:col_or_row row_count:4>
|
122
|
+
#
|
123
|
+
# Specify a single row by an \Integer index:
|
124
|
+
# # Get a row.
|
125
|
+
# table[1] # => #<CSV::Row "Name":"bar" "Value":"1">
|
126
|
+
# # Set a row, then get it.
|
127
|
+
# table[1] = CSV::Row.new(['Name', 'Value'], ['bam', 3])
|
128
|
+
# table[1] # => #<CSV::Row "Name":"bam" "Value":3>
|
129
|
+
#
|
130
|
+
# Specify a sequence of rows by a \Range:
|
131
|
+
# # Get rows.
|
132
|
+
# table[1..2] # => [#<CSV::Row "Name":"bam" "Value":3>, #<CSV::Row "Name":"baz" "Value":"2">]
|
133
|
+
# # Set rows, then get them.
|
134
|
+
# table[1] = CSV::Row.new(['Name', 'Value'], ['bat', 4])
|
135
|
+
# table[2] = CSV::Row.new(['Name', 'Value'], ['bad', 5])
|
136
|
+
# table[1..2] # => [["Name", #<CSV::Row "Name":"bat" "Value":4>], ["Value", #<CSV::Row "Name":"bad" "Value":5>]]
|
137
|
+
#
|
138
|
+
# Specify a column by its \String header:
|
139
|
+
# # Get a column.
|
140
|
+
# table['Name'] # => ["foo", "bat", "bad"]
|
141
|
+
# # Set a column, then get it.
|
142
|
+
# table['Name'] = ['Foo', 'Bar', 'Baz']
|
143
|
+
# table['Name'] # => ["Foo", "Bar", "Baz"]
|
14
144
|
class Table
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
145
|
+
# :call-seq:
|
146
|
+
# CSV::Table.new(array_of_rows, headers = nil)
|
147
|
+
#
|
148
|
+
# Returns a new \CSV::Table object.
|
149
|
+
#
|
150
|
+
# - Argument +array_of_rows+ must be an \Array of CSV::Row objects.
|
151
|
+
# - Argument +headers+, if given, may be an \Array of Strings.
|
152
|
+
#
|
153
|
+
# ---
|
154
|
+
#
|
155
|
+
# Create an empty \CSV::Table object:
|
156
|
+
# table = CSV::Table.new([])
|
157
|
+
# table # => #<CSV::Table mode:col_or_row row_count:1>
|
158
|
+
#
|
159
|
+
# Create a non-empty \CSV::Table object:
|
160
|
+
# rows = [
|
161
|
+
# CSV::Row.new([], []),
|
162
|
+
# CSV::Row.new([], []),
|
163
|
+
# CSV::Row.new([], []),
|
164
|
+
# ]
|
165
|
+
# table = CSV::Table.new(rows)
|
166
|
+
# table # => #<CSV::Table mode:col_or_row row_count:4>
|
167
|
+
#
|
168
|
+
# ---
|
169
|
+
#
|
170
|
+
# If argument +headers+ is an \Array of Strings,
|
171
|
+
# those Strings become the table's headers:
|
172
|
+
# table = CSV::Table.new([], headers: ['Name', 'Age'])
|
173
|
+
# table.headers # => ["Name", "Age"]
|
174
|
+
#
|
175
|
+
# If argument +headers+ is not given and the table has rows,
|
176
|
+
# the headers are taken from the first row:
|
177
|
+
# rows = [
|
178
|
+
# CSV::Row.new(['Foo', 'Bar'], []),
|
179
|
+
# CSV::Row.new(['foo', 'bar'], []),
|
180
|
+
# CSV::Row.new(['FOO', 'BAR'], []),
|
181
|
+
# ]
|
182
|
+
# table = CSV::Table.new(rows)
|
183
|
+
# table.headers # => ["Foo", "Bar"]
|
184
|
+
#
|
185
|
+
# If argument +headers+ is not given and the table is empty (has no rows),
|
186
|
+
# the headers are also empty:
|
187
|
+
# table = CSV::Table.new([])
|
188
|
+
# table.headers # => []
|
189
|
+
#
|
190
|
+
# ---
|
191
|
+
#
|
192
|
+
# Raises an exception if argument +array_of_rows+ is not an \Array object:
|
193
|
+
# # Raises NoMethodError (undefined method `first' for :foo:Symbol):
|
194
|
+
# CSV::Table.new(:foo)
|
195
|
+
#
|
196
|
+
# Raises an exception if an element of +array_of_rows+ is not a \CSV::Table object:
|
197
|
+
# # Raises NoMethodError (undefined method `headers' for :foo:Symbol):
|
198
|
+
# CSV::Table.new([:foo])
|
31
199
|
def initialize(array_of_rows, headers: nil)
|
32
200
|
@table = array_of_rows
|
33
201
|
@headers = headers
|
@@ -54,88 +222,141 @@ class CSV
|
|
54
222
|
extend Forwardable
|
55
223
|
def_delegators :@table, :empty?, :length, :size
|
56
224
|
|
225
|
+
# :call-seq:
|
226
|
+
# table.by_col
|
57
227
|
#
|
58
|
-
# Returns a duplicate
|
59
|
-
#
|
60
|
-
#
|
228
|
+
# Returns a duplicate of +self+, in column mode
|
229
|
+
# (see {Column Mode}[#class-CSV::Table-label-Column+Mode]):
|
230
|
+
# source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
|
231
|
+
# table = CSV.parse(source, headers: true)
|
232
|
+
# table.mode # => :col_or_row
|
233
|
+
# dup_table = table.by_col
|
234
|
+
# dup_table.mode # => :col
|
235
|
+
# dup_table.equal?(table) # => false # It's a dup
|
61
236
|
#
|
62
|
-
# This
|
63
|
-
#
|
64
|
-
#
|
237
|
+
# This may be used to chain method calls without changing the mode
|
238
|
+
# (but also will affect performance and memory usage):
|
239
|
+
# dup_table.by_col['Name']
|
65
240
|
#
|
241
|
+
# Also note that changes to the duplicate table will not affect the original.
|
66
242
|
def by_col
|
67
243
|
self.class.new(@table.dup).by_col!
|
68
244
|
end
|
69
245
|
|
70
|
-
#
|
71
|
-
#
|
72
|
-
#
|
73
|
-
#
|
74
|
-
#
|
75
|
-
#
|
246
|
+
# :call-seq:
|
247
|
+
# table.by_col!
|
248
|
+
#
|
249
|
+
# Sets the mode for +self+ to column mode
|
250
|
+
# (see {Column Mode}[#class-CSV::Table-label-Column+Mode]); returns +self+:
|
251
|
+
# source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
|
252
|
+
# table = CSV.parse(source, headers: true)
|
253
|
+
# table.mode # => :col_or_row
|
254
|
+
# table1 = table.by_col!
|
255
|
+
# table.mode # => :col
|
256
|
+
# table1.equal?(table) # => true # Returned self
|
76
257
|
def by_col!
|
77
258
|
@mode = :col
|
78
259
|
|
79
260
|
self
|
80
261
|
end
|
81
262
|
|
263
|
+
# :call-seq:
|
264
|
+
# table.by_col_or_row
|
82
265
|
#
|
83
|
-
# Returns a duplicate
|
84
|
-
#
|
85
|
-
#
|
266
|
+
# Returns a duplicate of +self+, in mixed mode
|
267
|
+
# (see {Mixed Mode}[#class-CSV::Table-label-Mixed+Mode]):
|
268
|
+
# source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
|
269
|
+
# table = CSV.parse(source, headers: true).by_col!
|
270
|
+
# table.mode # => :col
|
271
|
+
# dup_table = table.by_col_or_row
|
272
|
+
# dup_table.mode # => :col_or_row
|
273
|
+
# dup_table.equal?(table) # => false # It's a dup
|
86
274
|
#
|
87
|
-
# This
|
88
|
-
#
|
89
|
-
#
|
275
|
+
# This may be used to chain method calls without changing the mode
|
276
|
+
# (but also will affect performance and memory usage):
|
277
|
+
# dup_table.by_col_or_row['Name']
|
90
278
|
#
|
279
|
+
# Also note that changes to the duplicate table will not affect the original.
|
91
280
|
def by_col_or_row
|
92
281
|
self.class.new(@table.dup).by_col_or_row!
|
93
282
|
end
|
94
283
|
|
95
|
-
#
|
96
|
-
#
|
97
|
-
#
|
98
|
-
# the mode
|
99
|
-
#
|
100
|
-
#
|
101
|
-
#
|
102
|
-
#
|
284
|
+
# :call-seq:
|
285
|
+
# table.by_col_or_row!
|
286
|
+
#
|
287
|
+
# Sets the mode for +self+ to mixed mode
|
288
|
+
# (see {Mixed Mode}[#class-CSV::Table-label-Mixed+Mode]); returns +self+:
|
289
|
+
# source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
|
290
|
+
# table = CSV.parse(source, headers: true).by_col!
|
291
|
+
# table.mode # => :col
|
292
|
+
# table1 = table.by_col_or_row!
|
293
|
+
# table.mode # => :col_or_row
|
294
|
+
# table1.equal?(table) # => true # Returned self
|
103
295
|
def by_col_or_row!
|
104
296
|
@mode = :col_or_row
|
105
297
|
|
106
298
|
self
|
107
299
|
end
|
108
300
|
|
301
|
+
# :call-seq:
|
302
|
+
# table.by_row
|
109
303
|
#
|
110
|
-
# Returns a duplicate
|
111
|
-
#
|
112
|
-
#
|
304
|
+
# Returns a duplicate of +self+, in row mode
|
305
|
+
# (see {Row Mode}[#class-CSV::Table-label-Row+Mode]):
|
306
|
+
# source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
|
307
|
+
# table = CSV.parse(source, headers: true)
|
308
|
+
# table.mode # => :col_or_row
|
309
|
+
# dup_table = table.by_row
|
310
|
+
# dup_table.mode # => :row
|
311
|
+
# dup_table.equal?(table) # => false # It's a dup
|
113
312
|
#
|
114
|
-
# This
|
115
|
-
#
|
116
|
-
#
|
313
|
+
# This may be used to chain method calls without changing the mode
|
314
|
+
# (but also will affect performance and memory usage):
|
315
|
+
# dup_table.by_row[1]
|
117
316
|
#
|
317
|
+
# Also note that changes to the duplicate table will not affect the original.
|
118
318
|
def by_row
|
119
319
|
self.class.new(@table.dup).by_row!
|
120
320
|
end
|
121
321
|
|
122
|
-
#
|
123
|
-
#
|
124
|
-
#
|
125
|
-
#
|
126
|
-
#
|
127
|
-
#
|
322
|
+
# :call-seq:
|
323
|
+
# table.by_row!
|
324
|
+
#
|
325
|
+
# Sets the mode for +self+ to row mode
|
326
|
+
# (see {Row Mode}[#class-CSV::Table-label-Row+Mode]); returns +self+:
|
327
|
+
# source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
|
328
|
+
# table = CSV.parse(source, headers: true)
|
329
|
+
# table.mode # => :col_or_row
|
330
|
+
# table1 = table.by_row!
|
331
|
+
# table.mode # => :row
|
332
|
+
# table1.equal?(table) # => true # Returned self
|
128
333
|
def by_row!
|
129
334
|
@mode = :row
|
130
335
|
|
131
336
|
self
|
132
337
|
end
|
133
338
|
|
134
|
-
#
|
135
|
-
#
|
136
|
-
#
|
137
|
-
#
|
138
|
-
#
|
339
|
+
# :call-seq:
|
340
|
+
# table.headers
|
341
|
+
#
|
342
|
+
# Returns a new \Array containing the \String headers for the table.
|
343
|
+
#
|
344
|
+
# If the table is not empty, returns the headers from the first row:
|
345
|
+
# rows = [
|
346
|
+
# CSV::Row.new(['Foo', 'Bar'], []),
|
347
|
+
# CSV::Row.new(['FOO', 'BAR'], []),
|
348
|
+
# CSV::Row.new(['foo', 'bar'], []),
|
349
|
+
# ]
|
350
|
+
# table = CSV::Table.new(rows)
|
351
|
+
# table.headers # => ["Foo", "Bar"]
|
352
|
+
# table.delete(0)
|
353
|
+
# table.headers # => ["FOO", "BAR"]
|
354
|
+
# table.delete(0)
|
355
|
+
# table.headers # => ["foo", "bar"]
|
356
|
+
#
|
357
|
+
# If the table is empty, returns a copy of the headers in the table itself:
|
358
|
+
# table.delete(0)
|
359
|
+
# table.headers # => ["Foo", "Bar"]
|
139
360
|
def headers
|
140
361
|
if @table.empty?
|
141
362
|
@headers.dup
|
data/lib/csv/version.rb
CHANGED
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.
|
4
|
+
version: 3.1.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- James Edward Gray II
|
@@ -9,22 +9,8 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2020-
|
12
|
+
date: 2020-08-04 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
|
-
- !ruby/object:Gem::Dependency
|
15
|
-
name: stringio
|
16
|
-
requirement: !ruby/object:Gem::Requirement
|
17
|
-
requirements:
|
18
|
-
- - ">="
|
19
|
-
- !ruby/object:Gem::Version
|
20
|
-
version: 0.1.3
|
21
|
-
type: :runtime
|
22
|
-
prerelease: false
|
23
|
-
version_requirements: !ruby/object:Gem::Requirement
|
24
|
-
requirements:
|
25
|
-
- - ">="
|
26
|
-
- !ruby/object:Gem::Version
|
27
|
-
version: 0.1.3
|
28
14
|
- !ruby/object:Gem::Dependency
|
29
15
|
name: bundler
|
30
16
|
requirement: !ruby/object:Gem::Requirement
|
@@ -97,28 +83,28 @@ files:
|
|
97
83
|
- LICENSE.txt
|
98
84
|
- NEWS.md
|
99
85
|
- README.md
|
100
|
-
- doc/arguments/io.rdoc
|
101
|
-
- doc/options/common/col_sep.rdoc
|
102
|
-
- doc/options/common/quote_char.rdoc
|
103
|
-
- doc/options/common/row_sep.rdoc
|
104
|
-
- doc/options/generating/force_quotes.rdoc
|
105
|
-
- doc/options/generating/quote_empty.rdoc
|
106
|
-
- doc/options/generating/write_converters.rdoc
|
107
|
-
- doc/options/generating/write_empty_value.rdoc
|
108
|
-
- doc/options/generating/write_headers.rdoc
|
109
|
-
- doc/options/generating/write_nil_value.rdoc
|
110
|
-
- doc/options/parsing/converters.rdoc
|
111
|
-
- doc/options/parsing/empty_value.rdoc
|
112
|
-
- doc/options/parsing/field_size_limit.rdoc
|
113
|
-
- doc/options/parsing/header_converters.rdoc
|
114
|
-
- doc/options/parsing/headers.rdoc
|
115
|
-
- doc/options/parsing/liberal_parsing.rdoc
|
116
|
-
- doc/options/parsing/nil_value.rdoc
|
117
|
-
- doc/options/parsing/return_headers.rdoc
|
118
|
-
- doc/options/parsing/skip_blanks.rdoc
|
119
|
-
- doc/options/parsing/skip_lines.rdoc
|
120
|
-
- doc/options/parsing/strip.rdoc
|
121
|
-
- doc/options/parsing/unconverted_fields.rdoc
|
86
|
+
- doc/csv/arguments/io.rdoc
|
87
|
+
- doc/csv/options/common/col_sep.rdoc
|
88
|
+
- doc/csv/options/common/quote_char.rdoc
|
89
|
+
- doc/csv/options/common/row_sep.rdoc
|
90
|
+
- doc/csv/options/generating/force_quotes.rdoc
|
91
|
+
- doc/csv/options/generating/quote_empty.rdoc
|
92
|
+
- doc/csv/options/generating/write_converters.rdoc
|
93
|
+
- doc/csv/options/generating/write_empty_value.rdoc
|
94
|
+
- doc/csv/options/generating/write_headers.rdoc
|
95
|
+
- doc/csv/options/generating/write_nil_value.rdoc
|
96
|
+
- doc/csv/options/parsing/converters.rdoc
|
97
|
+
- doc/csv/options/parsing/empty_value.rdoc
|
98
|
+
- doc/csv/options/parsing/field_size_limit.rdoc
|
99
|
+
- doc/csv/options/parsing/header_converters.rdoc
|
100
|
+
- doc/csv/options/parsing/headers.rdoc
|
101
|
+
- doc/csv/options/parsing/liberal_parsing.rdoc
|
102
|
+
- doc/csv/options/parsing/nil_value.rdoc
|
103
|
+
- doc/csv/options/parsing/return_headers.rdoc
|
104
|
+
- doc/csv/options/parsing/skip_blanks.rdoc
|
105
|
+
- doc/csv/options/parsing/skip_lines.rdoc
|
106
|
+
- doc/csv/options/parsing/strip.rdoc
|
107
|
+
- doc/csv/options/parsing/unconverted_fields.rdoc
|
122
108
|
- lib/csv.rb
|
123
109
|
- lib/csv/core_ext/array.rb
|
124
110
|
- lib/csv/core_ext/string.rb
|
@@ -144,14 +130,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
144
130
|
requirements:
|
145
131
|
- - ">="
|
146
132
|
- !ruby/object:Gem::Version
|
147
|
-
version: 2.
|
133
|
+
version: 2.5.0
|
148
134
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
149
135
|
requirements:
|
150
136
|
- - ">="
|
151
137
|
- !ruby/object:Gem::Version
|
152
138
|
version: '0'
|
153
139
|
requirements: []
|
154
|
-
rubygems_version: 3.2.0.
|
140
|
+
rubygems_version: 3.2.0.rc.1
|
155
141
|
signing_key:
|
156
142
|
specification_version: 4
|
157
143
|
summary: CSV Reading and Writing
|