csv 3.1.9 → 3.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/NEWS.md +31 -0
- data/README.md +2 -5
- data/doc/csv/recipes/parsing.rdoc +2 -2
- data/lib/csv.rb +248 -135
- data/lib/csv/row.rb +22 -0
- data/lib/csv/table.rb +3 -1
- data/lib/csv/version.rb +1 -1
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c48c0d15454e002ff10270a9c56cf4311ce635a8a9dfb527f7a7541f29f801b2
|
4
|
+
data.tar.gz: 505d1d0dbb4cff0a544b2e00925cb1101ed71642a584d534f443405fba8bd820
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1c9ecd18d5b9a4f663c0676694ffc133a4657e2f7a07cafe2f0a5d9ddd2d7846f505bc62c21698fcf1117126efc6978b7aa1b497d2fef8d532a8a4246c58bff2
|
7
|
+
data.tar.gz: e4fe05b49f92c68c011060d1dcd39ead1785d886eabbd3689a12884df9eb30124694417314e39bcf656cd05d6d0dea6a80a701dd5fe6cac42efc33c67be54926
|
data/NEWS.md
CHANGED
@@ -1,5 +1,36 @@
|
|
1
1
|
# News
|
2
2
|
|
3
|
+
## 3.2.0 - 2021-06-06
|
4
|
+
|
5
|
+
### Improvements
|
6
|
+
|
7
|
+
* `CSV.open`: Added support for `:newline` option.
|
8
|
+
[GitHub#198][Patch by Nobuyoshi Nakada]
|
9
|
+
|
10
|
+
* `CSV::Table#each`: Added support for column mode with duplicated
|
11
|
+
headers.
|
12
|
+
[GitHub#206][Reported by Yaroslav Berezovskiy]
|
13
|
+
|
14
|
+
* `Object#CSV`: Added support for Ruby 3.0.
|
15
|
+
|
16
|
+
* `CSV::Row`: Added support for pattern matching.
|
17
|
+
[GitHub#207][Patch by Kevin Newton]
|
18
|
+
|
19
|
+
### Fixes
|
20
|
+
|
21
|
+
* Fixed typos in documentation.
|
22
|
+
[GitHub#196][GitHub#205][Patch by Sampat Badhe]
|
23
|
+
|
24
|
+
### Thanks
|
25
|
+
|
26
|
+
* Sampat Badhe
|
27
|
+
|
28
|
+
* Nobuyoshi Nakada
|
29
|
+
|
30
|
+
* Yaroslav Berezovskiy
|
31
|
+
|
32
|
+
* Kevin Newton
|
33
|
+
|
3
34
|
## 3.1.9 - 2020-11-23
|
4
35
|
|
5
36
|
### Fixes
|
data/README.md
CHANGED
@@ -1,8 +1,5 @@
|
|
1
1
|
# CSV
|
2
2
|
|
3
|
-
[![Build Status](https://travis-ci.org/ruby/csv.svg?branch=master)](https://travis-ci.org/ruby/csv)
|
4
|
-
[![Test Coverage](https://api.codeclimate.com/v1/badges/321fa39e510a0abd0369/test_coverage)](https://codeclimate.com/github/ruby/csv/test_coverage)
|
5
|
-
|
6
3
|
This library provides a complete interface to CSV files and data. It offers tools to enable you to read and write to and from Strings or IO objects, as needed.
|
7
4
|
|
8
5
|
## Installation
|
@@ -33,8 +30,8 @@ end
|
|
33
30
|
|
34
31
|
## Documentation
|
35
32
|
|
36
|
-
-
|
37
|
-
-
|
33
|
+
- [API](https://ruby-doc.org/stdlib/libdoc/csv/rdoc/CSV.html): all classes, methods, and constants.
|
34
|
+
- [Recipes](https://ruby-doc.org/core/doc/csv/recipes/recipes_rdoc.html): specific code for specific tasks.
|
38
35
|
|
39
36
|
## Development
|
40
37
|
|
@@ -431,7 +431,7 @@ You can use multiple field converters in either of these ways:
|
|
431
431
|
|
432
432
|
===== Recipe: Specify Multiple Field Converters in Option +:converters+
|
433
433
|
|
434
|
-
Apply multiple field converters by specifying them in option +:
|
434
|
+
Apply multiple field converters by specifying them in option +:converters+:
|
435
435
|
source = "Name,Value\nfoo,0\nbar,1.0\nbaz,2.0\n"
|
436
436
|
parsed = CSV.parse(source, headers: true, converters: [:integer, :float])
|
437
437
|
parsed['Value'] # => [0, 1.0, 2.0]
|
@@ -500,7 +500,7 @@ You can use multiple header converters in either of these ways:
|
|
500
500
|
|
501
501
|
===== Recipe: Specify Multiple Header Converters in Option :header_converters
|
502
502
|
|
503
|
-
Apply multiple header converters by specifying them in option +:
|
503
|
+
Apply multiple header converters by specifying them in option +:header_converters+:
|
504
504
|
source = "Name,Value\nfoo,0\nbar,1.0\nbaz,2.0\n"
|
505
505
|
parsed = CSV.parse(source, headers: true, header_converters: [:downcase, :symbol])
|
506
506
|
parsed.headers # => [:name, :value]
|
data/lib/csv.rb
CHANGED
@@ -48,7 +48,7 @@
|
|
48
48
|
#
|
49
49
|
# === Interface
|
50
50
|
#
|
51
|
-
# * CSV now uses
|
51
|
+
# * CSV now uses keyword parameters to set options.
|
52
52
|
# * CSV no longer has generate_row() or parse_row().
|
53
53
|
# * The old CSV's Reader and Writer classes have been dropped.
|
54
54
|
# * CSV::open() is now more like Ruby's open().
|
@@ -705,7 +705,7 @@ using CSV::MatchP if CSV.const_defined?(:MatchP)
|
|
705
705
|
# Header converters operate only on headers (and not on other rows).
|
706
706
|
#
|
707
707
|
# There are three ways to use header \converters;
|
708
|
-
# these examples use built-in header converter +:
|
708
|
+
# these examples use built-in header converter +:downcase+,
|
709
709
|
# which downcases each parsed header.
|
710
710
|
#
|
711
711
|
# - Option +header_converters+ with a singleton parsing method:
|
@@ -1006,60 +1006,185 @@ class CSV
|
|
1006
1006
|
end
|
1007
1007
|
|
1008
1008
|
# :call-seq:
|
1009
|
-
# filter(**options) {|row| ... }
|
1010
|
-
# filter(
|
1011
|
-
# filter(
|
1012
|
-
# filter(in_string, out_string, **options) {|row| ... }
|
1013
|
-
# filter(in_string, out_io, **options) {|row| ... }
|
1014
|
-
# filter(in_io, out_string, **options) {|row| ... }
|
1015
|
-
# filter(in_io, out_io, **options) {|row| ... }
|
1016
|
-
#
|
1017
|
-
# Reads \CSV input and writes \CSV output.
|
1018
|
-
#
|
1019
|
-
# For each input row:
|
1020
|
-
# - Forms the data into:
|
1021
|
-
# - A CSV::Row object, if headers are in use.
|
1022
|
-
# - An \Array of Arrays, otherwise.
|
1023
|
-
# - Calls the block with that object.
|
1024
|
-
# - Appends the block's return value to the output.
|
1009
|
+
# filter(in_string_or_io, **options) {|row| ... } -> array_of_arrays or csv_table
|
1010
|
+
# filter(in_string_or_io, out_string_or_io, **options) {|row| ... } -> array_of_arrays or csv_table
|
1011
|
+
# filter(**options) {|row| ... } -> array_of_arrays or csv_table
|
1025
1012
|
#
|
1026
|
-
#
|
1027
|
-
#
|
1028
|
-
#
|
1029
|
-
#
|
1030
|
-
#
|
1031
|
-
#
|
1032
|
-
#
|
1033
|
-
#
|
1034
|
-
# * \CSV output:
|
1035
|
-
# * Argument +out_string+, if given, should be a \String object;
|
1036
|
-
# it will be put into a new StringIO object positioned at the beginning.
|
1037
|
-
# * Argument +out_io+, if given, should be an IO object that is
|
1038
|
-
# ppen for writing; on return, the IO object will be closed.
|
1039
|
-
# * If neither +out_string+ nor +out_io+ is given,
|
1040
|
-
# the output stream defaults to <tt>$stdout</tt>.
|
1041
|
-
# * Argument +options+ should be keyword arguments.
|
1042
|
-
# - Each argument name that is prefixed with +in_+ or +input_+
|
1043
|
-
# is stripped of its prefix and is treated as an option
|
1044
|
-
# for parsing the input.
|
1045
|
-
# Option +input_row_sep+ defaults to <tt>$INPUT_RECORD_SEPARATOR</tt>.
|
1046
|
-
# - Each argument name that is prefixed with +out_+ or +output_+
|
1047
|
-
# is stripped of its prefix and is treated as an option
|
1048
|
-
# for generating the output.
|
1049
|
-
# Option +output_row_sep+ defaults to <tt>$INPUT_RECORD_SEPARATOR</tt>.
|
1050
|
-
# - Each argument not prefixed as above is treated as an option
|
1051
|
-
# both for parsing the input and for generating the output.
|
1052
|
-
# - See {Options for Parsing}[#class-CSV-label-Options+for+Parsing]
|
1053
|
-
# and {Options for Generating}[#class-CSV-label-Options+for+Generating].
|
1013
|
+
# - Parses \CSV from a source (\String, \IO stream, or ARGF).
|
1014
|
+
# - Calls the given block with each parsed row:
|
1015
|
+
# - Without headers, each row is an \Array.
|
1016
|
+
# - With headers, each row is a CSV::Row.
|
1017
|
+
# - Generates \CSV to an output (\String, \IO stream, or STDOUT).
|
1018
|
+
# - Returns the parsed source:
|
1019
|
+
# - Without headers, an \Array of \Arrays.
|
1020
|
+
# - With headers, a CSV::Table.
|
1054
1021
|
#
|
1055
|
-
#
|
1056
|
-
#
|
1022
|
+
# When +in_string_or_io+ is given, but not +out_string_or_io+,
|
1023
|
+
# parses from the given +in_string_or_io+
|
1024
|
+
# and generates to STDOUT.
|
1025
|
+
#
|
1026
|
+
# \String input without headers:
|
1027
|
+
#
|
1028
|
+
# in_string = "foo,0\nbar,1\nbaz,2"
|
1029
|
+
# CSV.filter(in_string) do |row|
|
1030
|
+
# row[0].upcase!
|
1031
|
+
# row[1] = - row[1].to_i
|
1032
|
+
# end # => [["FOO", 0], ["BAR", -1], ["BAZ", -2]]
|
1033
|
+
#
|
1034
|
+
# Output (to STDOUT):
|
1035
|
+
#
|
1036
|
+
# FOO,0
|
1037
|
+
# BAR,-1
|
1038
|
+
# BAZ,-2
|
1039
|
+
#
|
1040
|
+
# \String input with headers:
|
1041
|
+
#
|
1042
|
+
# in_string = "Name,Value\nfoo,0\nbar,1\nbaz,2"
|
1043
|
+
# CSV.filter(in_string, headers: true) do |row|
|
1044
|
+
# row[0].upcase!
|
1045
|
+
# row[1] = - row[1].to_i
|
1046
|
+
# end # => #<CSV::Table mode:col_or_row row_count:4>
|
1047
|
+
#
|
1048
|
+
# Output (to STDOUT):
|
1049
|
+
#
|
1050
|
+
# Name,Value
|
1051
|
+
# FOO,0
|
1052
|
+
# BAR,-1
|
1053
|
+
# BAZ,-2
|
1054
|
+
#
|
1055
|
+
# \IO stream input without headers:
|
1056
|
+
#
|
1057
|
+
# File.write('t.csv', "foo,0\nbar,1\nbaz,2")
|
1058
|
+
# File.open('t.csv') do |in_io|
|
1059
|
+
# CSV.filter(in_io) do |row|
|
1060
|
+
# row[0].upcase!
|
1061
|
+
# row[1] = - row[1].to_i
|
1062
|
+
# end
|
1063
|
+
# end # => [["FOO", 0], ["BAR", -1], ["BAZ", -2]]
|
1064
|
+
#
|
1065
|
+
# Output (to STDOUT):
|
1066
|
+
#
|
1067
|
+
# FOO,0
|
1068
|
+
# BAR,-1
|
1069
|
+
# BAZ,-2
|
1070
|
+
#
|
1071
|
+
# \IO stream input with headers:
|
1072
|
+
#
|
1073
|
+
# File.write('t.csv', "Name,Value\nfoo,0\nbar,1\nbaz,2")
|
1074
|
+
# File.open('t.csv') do |in_io|
|
1075
|
+
# CSV.filter(in_io, headers: true) do |row|
|
1076
|
+
# row[0].upcase!
|
1077
|
+
# row[1] = - row[1].to_i
|
1078
|
+
# end
|
1079
|
+
# end # => #<CSV::Table mode:col_or_row row_count:4>
|
1080
|
+
#
|
1081
|
+
# Output (to STDOUT):
|
1082
|
+
#
|
1083
|
+
# Name,Value
|
1084
|
+
# FOO,0
|
1085
|
+
# BAR,-1
|
1086
|
+
# BAZ,-2
|
1087
|
+
#
|
1088
|
+
# When both +in_string_or_io+ and +out_string_or_io+ are given,
|
1089
|
+
# parses from +in_string_or_io+ and generates to +out_string_or_io+.
|
1090
|
+
#
|
1091
|
+
# \String output without headers:
|
1092
|
+
#
|
1093
|
+
# in_string = "foo,0\nbar,1\nbaz,2"
|
1057
1094
|
# out_string = ''
|
1058
1095
|
# CSV.filter(in_string, out_string) do |row|
|
1059
|
-
# row[0]
|
1060
|
-
# row[1]
|
1061
|
-
# end
|
1062
|
-
# out_string # => "FOO,
|
1096
|
+
# row[0].upcase!
|
1097
|
+
# row[1] = - row[1].to_i
|
1098
|
+
# end # => [["FOO", 0], ["BAR", -1], ["BAZ", -2]]
|
1099
|
+
# out_string # => "FOO,0\nBAR,-1\nBAZ,-2\n"
|
1100
|
+
#
|
1101
|
+
# \String output with headers:
|
1102
|
+
#
|
1103
|
+
# in_string = "Name,Value\nfoo,0\nbar,1\nbaz,2"
|
1104
|
+
# out_string = ''
|
1105
|
+
# CSV.filter(in_string, out_string, headers: true) do |row|
|
1106
|
+
# row[0].upcase!
|
1107
|
+
# row[1] = - row[1].to_i
|
1108
|
+
# end # => #<CSV::Table mode:col_or_row row_count:4>
|
1109
|
+
# out_string # => "Name,Value\nFOO,0\nBAR,-1\nBAZ,-2\n"
|
1110
|
+
#
|
1111
|
+
# \IO stream output without headers:
|
1112
|
+
#
|
1113
|
+
# in_string = "foo,0\nbar,1\nbaz,2"
|
1114
|
+
# File.open('t.csv', 'w') do |out_io|
|
1115
|
+
# CSV.filter(in_string, out_io) do |row|
|
1116
|
+
# row[0].upcase!
|
1117
|
+
# row[1] = - row[1].to_i
|
1118
|
+
# end
|
1119
|
+
# end # => [["FOO", 0], ["BAR", -1], ["BAZ", -2]]
|
1120
|
+
# File.read('t.csv') # => "FOO,0\nBAR,-1\nBAZ,-2\n"
|
1121
|
+
#
|
1122
|
+
# \IO stream output with headers:
|
1123
|
+
#
|
1124
|
+
# in_string = "Name,Value\nfoo,0\nbar,1\nbaz,2"
|
1125
|
+
# File.open('t.csv', 'w') do |out_io|
|
1126
|
+
# CSV.filter(in_string, out_io, headers: true) do |row|
|
1127
|
+
# row[0].upcase!
|
1128
|
+
# row[1] = - row[1].to_i
|
1129
|
+
# end
|
1130
|
+
# end # => #<CSV::Table mode:col_or_row row_count:4>
|
1131
|
+
# File.read('t.csv') # => "Name,Value\nFOO,0\nBAR,-1\nBAZ,-2\n"
|
1132
|
+
#
|
1133
|
+
# When neither +in_string_or_io+ nor +out_string_or_io+ given,
|
1134
|
+
# parses from {ARGF}[https://docs.ruby-lang.org/en/master/ARGF.html]
|
1135
|
+
# and generates to STDOUT.
|
1136
|
+
#
|
1137
|
+
# Without headers:
|
1138
|
+
#
|
1139
|
+
# # Put Ruby code into a file.
|
1140
|
+
# ruby = <<-EOT
|
1141
|
+
# require 'csv'
|
1142
|
+
# CSV.filter do |row|
|
1143
|
+
# row[0].upcase!
|
1144
|
+
# row[1] = - row[1].to_i
|
1145
|
+
# end
|
1146
|
+
# EOT
|
1147
|
+
# File.write('t.rb', ruby)
|
1148
|
+
# # Put some CSV into a file.
|
1149
|
+
# File.write('t.csv', "foo,0\nbar,1\nbaz,2")
|
1150
|
+
# # Run the Ruby code with CSV filename as argument.
|
1151
|
+
# system(Gem.ruby, "t.rb", "t.csv")
|
1152
|
+
#
|
1153
|
+
# Output (to STDOUT):
|
1154
|
+
#
|
1155
|
+
# FOO,0
|
1156
|
+
# BAR,-1
|
1157
|
+
# BAZ,-2
|
1158
|
+
#
|
1159
|
+
# With headers:
|
1160
|
+
#
|
1161
|
+
# # Put Ruby code into a file.
|
1162
|
+
# ruby = <<-EOT
|
1163
|
+
# require 'csv'
|
1164
|
+
# CSV.filter(headers: true) do |row|
|
1165
|
+
# row[0].upcase!
|
1166
|
+
# row[1] = - row[1].to_i
|
1167
|
+
# end
|
1168
|
+
# EOT
|
1169
|
+
# File.write('t.rb', ruby)
|
1170
|
+
# # Put some CSV into a file.
|
1171
|
+
# File.write('t.csv', "Name,Value\nfoo,0\nbar,1\nbaz,2")
|
1172
|
+
# # Run the Ruby code with CSV filename as argument.
|
1173
|
+
# system(Gem.ruby, "t.rb", "t.csv")
|
1174
|
+
#
|
1175
|
+
# Output (to STDOUT):
|
1176
|
+
#
|
1177
|
+
# Name,Value
|
1178
|
+
# FOO,0
|
1179
|
+
# BAR,-1
|
1180
|
+
# BAZ,-2
|
1181
|
+
#
|
1182
|
+
# Arguments:
|
1183
|
+
#
|
1184
|
+
# * Argument +in_string_or_io+ must be a \String or an \IO stream.
|
1185
|
+
# * Argument +out_string_or_io+ must be a \String or an \IO stream.
|
1186
|
+
# * Arguments <tt>**options</tt> must be keyword options.
|
1187
|
+
# See {Options for Parsing}[#class-CSV-label-Options+for+Parsing].
|
1063
1188
|
def filter(input=nil, output=nil, **options)
|
1064
1189
|
# parse options for input, output, or both
|
1065
1190
|
in_options, out_options = Hash.new, {row_sep: $INPUT_RECORD_SEPARATOR}
|
@@ -1106,111 +1231,90 @@ class CSV
|
|
1106
1231
|
|
1107
1232
|
#
|
1108
1233
|
# :call-seq:
|
1109
|
-
# foreach(
|
1110
|
-
# foreach(
|
1111
|
-
# foreach(path, mode='r', headers: ..., **options) {|row| ... )
|
1112
|
-
# foreach(io, mode='r', headers: ..., **options {|row| ... )
|
1113
|
-
# foreach(path, mode='r', **options) -> new_enumerator
|
1114
|
-
# foreach(io, mode='r', **options -> new_enumerator
|
1234
|
+
# foreach(path_or_io, mode='r', **options) {|row| ... )
|
1235
|
+
# foreach(path_or_io, mode='r', **options) -> new_enumerator
|
1115
1236
|
#
|
1116
|
-
# Calls the block with each row read from source +
|
1237
|
+
# Calls the block with each row read from source +path_or_io+.
|
1117
1238
|
#
|
1118
|
-
#
|
1119
|
-
# :include: ../doc/csv/arguments/io.rdoc
|
1120
|
-
# * Argument +mode+, if given, must be a \File mode
|
1121
|
-
# See {Open Mode}[IO.html#method-c-new-label-Open+Mode].
|
1122
|
-
# * Arguments <tt>**options</tt> must be keyword options.
|
1123
|
-
# See {Options for Parsing}[#class-CSV-label-Options+for+Parsing].
|
1124
|
-
# * This method optionally accepts an additional <tt>:encoding</tt> option
|
1125
|
-
# that you can use to specify the Encoding of the data read from +path+ or +io+.
|
1126
|
-
# You must provide this unless your data is in the encoding
|
1127
|
-
# given by <tt>Encoding::default_external</tt>.
|
1128
|
-
# Parsing will use this to determine how to parse the data.
|
1129
|
-
# You may provide a second Encoding to
|
1130
|
-
# have the data transcoded as it is read. For example,
|
1131
|
-
# encoding: 'UTF-32BE:UTF-8'
|
1132
|
-
# would read +UTF-32BE+ data from the file
|
1133
|
-
# but transcode it to +UTF-8+ before parsing.
|
1134
|
-
#
|
1135
|
-
# ====== Without Option +headers+
|
1239
|
+
# \Path input without headers:
|
1136
1240
|
#
|
1137
|
-
# Without option +headers+, returns each row as an \Array object.
|
1138
|
-
#
|
1139
|
-
# These examples assume prior execution of:
|
1140
1241
|
# string = "foo,0\nbar,1\nbaz,2\n"
|
1141
|
-
#
|
1142
|
-
# File.write(
|
1242
|
+
# in_path = 't.csv'
|
1243
|
+
# File.write(in_path, string)
|
1244
|
+
# CSV.foreach(in_path) {|row| p row }
|
1143
1245
|
#
|
1144
|
-
# Read rows from a file at +path+:
|
1145
|
-
# CSV.foreach(path) {|row| p row }
|
1146
1246
|
# Output:
|
1147
|
-
# ["foo", "0"]
|
1148
|
-
# ["bar", "1"]
|
1149
|
-
# ["baz", "2"]
|
1150
1247
|
#
|
1151
|
-
# Read rows from an \IO object:
|
1152
|
-
# File.open(path) do |file|
|
1153
|
-
# CSV.foreach(file) {|row| p row }
|
1154
|
-
# end
|
1155
|
-
#
|
1156
|
-
# Output:
|
1157
1248
|
# ["foo", "0"]
|
1158
1249
|
# ["bar", "1"]
|
1159
1250
|
# ["baz", "2"]
|
1160
1251
|
#
|
1161
|
-
#
|
1162
|
-
#
|
1163
|
-
#
|
1252
|
+
# \Path input with headers:
|
1253
|
+
#
|
1254
|
+
# string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
|
1255
|
+
# in_path = 't.csv'
|
1256
|
+
# File.write(in_path, string)
|
1257
|
+
# CSV.foreach(in_path, headers: true) {|row| p row }
|
1164
1258
|
#
|
1165
|
-
# Issues a warning if an encoding is unsupported:
|
1166
|
-
# CSV.foreach(File.open(path), encoding: 'foo:bar') {|row| }
|
1167
1259
|
# Output:
|
1168
|
-
# warning: Unsupported encoding foo ignored
|
1169
|
-
# warning: Unsupported encoding bar ignored
|
1170
1260
|
#
|
1171
|
-
#
|
1261
|
+
# <CSV::Row "Name":"foo" "Value":"0">
|
1262
|
+
# <CSV::Row "Name":"bar" "Value":"1">
|
1263
|
+
# <CSV::Row "Name":"baz" "Value":"2">
|
1172
1264
|
#
|
1173
|
-
#
|
1174
|
-
# returns each row as a CSV::Row object.
|
1265
|
+
# \IO stream input without headers:
|
1175
1266
|
#
|
1176
|
-
#
|
1177
|
-
# string = "Name,Count\nfoo,0\nbar,1\nbaz,2\n"
|
1267
|
+
# string = "foo,0\nbar,1\nbaz,2\n"
|
1178
1268
|
# path = 't.csv'
|
1179
1269
|
# File.write(path, string)
|
1180
|
-
#
|
1181
|
-
#
|
1182
|
-
#
|
1270
|
+
# File.open('t.csv') do |in_io|
|
1271
|
+
# CSV.foreach(in_io) {|row| p row }
|
1272
|
+
# end
|
1183
1273
|
#
|
1184
1274
|
# Output:
|
1185
|
-
# #<CSV::Row "Name":"foo" "Count":"0">
|
1186
|
-
# #<CSV::Row "Name":"bar" "Count":"1">
|
1187
|
-
# #<CSV::Row "Name":"baz" "Count":"2">
|
1188
1275
|
#
|
1189
|
-
#
|
1190
|
-
#
|
1191
|
-
#
|
1276
|
+
# ["foo", "0"]
|
1277
|
+
# ["bar", "1"]
|
1278
|
+
# ["baz", "2"]
|
1279
|
+
#
|
1280
|
+
# \IO stream input with headers:
|
1281
|
+
#
|
1282
|
+
# string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
|
1283
|
+
# path = 't.csv'
|
1284
|
+
# File.write(path, string)
|
1285
|
+
# File.open('t.csv') do |in_io|
|
1286
|
+
# CSV.foreach(in_io, headers: true) {|row| p row }
|
1192
1287
|
# end
|
1193
1288
|
#
|
1194
1289
|
# Output:
|
1195
|
-
# #<CSV::Row "Name":"foo" "Count":"0">
|
1196
|
-
# #<CSV::Row "Name":"bar" "Count":"1">
|
1197
|
-
# #<CSV::Row "Name":"baz" "Count":"2">
|
1198
1290
|
#
|
1199
|
-
#
|
1291
|
+
# <CSV::Row "Name":"foo" "Value":"0">
|
1292
|
+
# <CSV::Row "Name":"bar" "Value":"1">
|
1293
|
+
# <CSV::Row "Name":"baz" "Value":"2">
|
1200
1294
|
#
|
1201
|
-
#
|
1202
|
-
# # Raises Errno::ENOENT (No such file or directory @ rb_sysopen - nosuch.csv):
|
1203
|
-
# CSV.foreach('nosuch.csv') {|row| }
|
1295
|
+
# With no block given, returns an \Enumerator:
|
1204
1296
|
#
|
1205
|
-
#
|
1206
|
-
#
|
1207
|
-
#
|
1208
|
-
# CSV.foreach(
|
1209
|
-
#
|
1210
|
-
# Raises an exception if +mode+ is invalid:
|
1211
|
-
# # Raises ArgumentError (invalid access mode nosuch):
|
1212
|
-
# CSV.foreach(path, 'nosuch') {|row| }
|
1297
|
+
# string = "foo,0\nbar,1\nbaz,2\n"
|
1298
|
+
# path = 't.csv'
|
1299
|
+
# File.write(path, string)
|
1300
|
+
# CSV.foreach(path) # => #<Enumerator: CSV:foreach("t.csv", "r")>
|
1213
1301
|
#
|
1302
|
+
# Arguments:
|
1303
|
+
# * Argument +path_or_io+ must be a file path or an \IO stream.
|
1304
|
+
# * Argument +mode+, if given, must be a \File mode
|
1305
|
+
# See {Open Mode}[https://ruby-doc.org/core/IO.html#method-c-new-label-Open+Mode].
|
1306
|
+
# * Arguments <tt>**options</tt> must be keyword options.
|
1307
|
+
# See {Options for Parsing}[#class-CSV-label-Options+for+Parsing].
|
1308
|
+
# * This method optionally accepts an additional <tt>:encoding</tt> option
|
1309
|
+
# that you can use to specify the Encoding of the data read from +path+ or +io+.
|
1310
|
+
# You must provide this unless your data is in the encoding
|
1311
|
+
# given by <tt>Encoding::default_external</tt>.
|
1312
|
+
# Parsing will use this to determine how to parse the data.
|
1313
|
+
# You may provide a second Encoding to
|
1314
|
+
# have the data transcoded as it is read. For example,
|
1315
|
+
# encoding: 'UTF-32BE:UTF-8'
|
1316
|
+
# would read +UTF-32BE+ data from the file
|
1317
|
+
# but transcode it to +UTF-8+ before parsing.
|
1214
1318
|
def foreach(path, mode="r", **options, &block)
|
1215
1319
|
return to_enum(__method__, path, mode, **options) unless block_given?
|
1216
1320
|
open(path, mode, **options) do |csv|
|
@@ -1356,7 +1460,7 @@ class CSV
|
|
1356
1460
|
# open(io, mode = "rb", **options ) { |csv| ... } -> object
|
1357
1461
|
#
|
1358
1462
|
# possible options elements:
|
1359
|
-
#
|
1463
|
+
# keyword form:
|
1360
1464
|
# :invalid => nil # raise error on invalid byte sequence (default)
|
1361
1465
|
# :invalid => :replace # replace invalid byte sequence
|
1362
1466
|
# :undef => :replace # replace undefined conversion
|
@@ -1423,10 +1527,14 @@ class CSV
|
|
1423
1527
|
def open(filename, mode="r", **options)
|
1424
1528
|
# wrap a File opened with the remaining +args+ with no newline
|
1425
1529
|
# decorator
|
1426
|
-
file_opts =
|
1530
|
+
file_opts = options.dup
|
1531
|
+
unless file_opts.key?(:newline)
|
1532
|
+
file_opts[:universal_newline] ||= false
|
1533
|
+
end
|
1427
1534
|
options.delete(:invalid)
|
1428
1535
|
options.delete(:undef)
|
1429
1536
|
options.delete(:replace)
|
1537
|
+
options.delete_if {|k, _| /newline\z/.match?(k)}
|
1430
1538
|
|
1431
1539
|
begin
|
1432
1540
|
f = File.open(filename, mode, **file_opts)
|
@@ -1681,7 +1789,7 @@ class CSV
|
|
1681
1789
|
#
|
1682
1790
|
# Calls CSV.read with +source+, +options+, and certain default options:
|
1683
1791
|
# - +headers+: +true+
|
1684
|
-
# - +
|
1792
|
+
# - +converters+: +:numeric+
|
1685
1793
|
# - +header_converters+: +:symbol+
|
1686
1794
|
#
|
1687
1795
|
# Returns a CSV::Table object.
|
@@ -1985,7 +2093,7 @@ class CSV
|
|
1985
2093
|
end
|
1986
2094
|
|
1987
2095
|
# :call-seq:
|
1988
|
-
# csv.encoding ->
|
2096
|
+
# csv.encoding -> encoding
|
1989
2097
|
#
|
1990
2098
|
# Returns the encoding used for parsing and generating;
|
1991
2099
|
# see {Character Encodings (M17n or Multilingualization)}[#class-CSV-label-Character+Encodings+-28M17n+or+Multilingualization-29]:
|
@@ -2661,8 +2769,13 @@ end
|
|
2661
2769
|
# c.read.any? { |a| a.include?("zombies") }
|
2662
2770
|
# } #=> false
|
2663
2771
|
#
|
2664
|
-
|
2665
|
-
|
2772
|
+
# CSV options may also be given.
|
2773
|
+
#
|
2774
|
+
# io = StringIO.new
|
2775
|
+
# CSV(io, col_sep: ";") { |csv| csv << ["a", "b", "c"] }
|
2776
|
+
#
|
2777
|
+
def CSV(*args, **options, &block)
|
2778
|
+
CSV.instance(*args, **options, &block)
|
2666
2779
|
end
|
2667
2780
|
|
2668
2781
|
require_relative "csv/version"
|
data/lib/csv/row.rb
CHANGED
@@ -659,8 +659,30 @@ class CSV
|
|
659
659
|
end
|
660
660
|
alias_method :to_hash, :to_h
|
661
661
|
|
662
|
+
# :call-seq:
|
663
|
+
# row.deconstruct_keys(keys) -> hash
|
664
|
+
#
|
665
|
+
# Returns the new \Hash suitable for pattern matching containing only the
|
666
|
+
# keys specified as an argument.
|
667
|
+
def deconstruct_keys(keys)
|
668
|
+
if keys.nil?
|
669
|
+
to_h
|
670
|
+
else
|
671
|
+
keys.to_h { |key| [key, self[key]] }
|
672
|
+
end
|
673
|
+
end
|
674
|
+
|
662
675
|
alias_method :to_ary, :to_a
|
663
676
|
|
677
|
+
# :call-seq:
|
678
|
+
# row.deconstruct -> array
|
679
|
+
#
|
680
|
+
# Returns the new \Array suitable for pattern matching containing the values
|
681
|
+
# of the row.
|
682
|
+
def deconstruct
|
683
|
+
fields
|
684
|
+
end
|
685
|
+
|
664
686
|
# :call-seq:
|
665
687
|
# row.to_csv -> csv_string
|
666
688
|
#
|
data/lib/csv/table.rb
CHANGED
@@ -932,7 +932,9 @@ class CSV
|
|
932
932
|
return enum_for(__method__) { @mode == :col ? headers.size : size } unless block_given?
|
933
933
|
|
934
934
|
if @mode == :col
|
935
|
-
headers.each
|
935
|
+
headers.each.with_index do |header, i|
|
936
|
+
yield([header, @table.map {|row| row[header, i]}])
|
937
|
+
end
|
936
938
|
else
|
937
939
|
@table.each(&block)
|
938
940
|
end
|
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.
|
4
|
+
version: 3.2.0
|
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:
|
12
|
+
date: 2021-06-05 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -54,19 +54,19 @@ dependencies:
|
|
54
54
|
- !ruby/object:Gem::Version
|
55
55
|
version: '0'
|
56
56
|
- !ruby/object:Gem::Dependency
|
57
|
-
name:
|
57
|
+
name: test-unit
|
58
58
|
requirement: !ruby/object:Gem::Requirement
|
59
59
|
requirements:
|
60
60
|
- - ">="
|
61
61
|
- !ruby/object:Gem::Version
|
62
|
-
version:
|
62
|
+
version: 3.4.3
|
63
63
|
type: :development
|
64
64
|
prerelease: false
|
65
65
|
version_requirements: !ruby/object:Gem::Requirement
|
66
66
|
requirements:
|
67
67
|
- - ">="
|
68
68
|
- !ruby/object:Gem::Version
|
69
|
-
version:
|
69
|
+
version: 3.4.3
|
70
70
|
description: The CSV library provides a complete interface to CSV files and data.
|
71
71
|
It offers tools to enable you to read and write to and from Strings or IO objects,
|
72
72
|
as needed.
|
@@ -146,7 +146,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
146
146
|
- !ruby/object:Gem::Version
|
147
147
|
version: '0'
|
148
148
|
requirements: []
|
149
|
-
rubygems_version: 3.
|
149
|
+
rubygems_version: 3.3.0.dev
|
150
150
|
signing_key:
|
151
151
|
specification_version: 4
|
152
152
|
summary: CSV Reading and Writing
|