csv 3.1.9 → 3.2.0
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 +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
|
-
[](https://travis-ci.org/ruby/csv)
|
4
|
-
[](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
|