iostreams 1.11.0 → 2.1.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/README.md +14 -13
- data/Rakefile +52 -0
- data/docs/CLAUDE.md +9 -0
- data/docs/config.md +157 -0
- data/docs/copy_files.md +75 -0
- data/docs/extensions.md +111 -0
- data/docs/formats.md +188 -0
- data/docs/index.md +388 -0
- data/docs/path.md +652 -0
- data/docs/pgp.md +436 -0
- data/docs/streams.md +337 -0
- data/docs/tutorial.md +483 -0
- data/docs/upgrading.md +217 -0
- data/lib/io_streams/builder.rb +71 -11
- data/lib/io_streams/bzip2/reader.rb +25 -2
- data/lib/io_streams/bzip2/writer.rb +26 -2
- data/lib/io_streams/encode/reader.rb +6 -2
- data/lib/io_streams/encode/writer.rb +9 -5
- data/lib/io_streams/errors.rb +4 -0
- data/lib/io_streams/gzip/reader.rb +5 -1
- data/lib/io_streams/gzip/writer.rb +11 -2
- data/lib/io_streams/io_streams.rb +156 -20
- data/lib/io_streams/line/reader.rb +9 -4
- data/lib/io_streams/line/writer.rb +1 -1
- data/lib/io_streams/path.rb +117 -8
- data/lib/io_streams/paths/file.rb +57 -11
- data/lib/io_streams/paths/http.rb +123 -9
- data/lib/io_streams/paths/matcher.rb +3 -3
- data/lib/io_streams/paths/s3.rb +69 -18
- data/lib/io_streams/paths/sftp/net_ssh.rb +104 -0
- data/lib/io_streams/paths/sftp.rb +103 -64
- data/lib/io_streams/pgp/reader.rb +63 -10
- data/lib/io_streams/pgp/writer.rb +111 -30
- data/lib/io_streams/pgp.rb +256 -71
- data/lib/io_streams/reader.rb +14 -5
- data/lib/io_streams/record/reader.rb +75 -6
- data/lib/io_streams/record/writer.rb +3 -4
- data/lib/io_streams/row/reader.rb +1 -1
- data/lib/io_streams/row/writer.rb +1 -1
- data/lib/io_streams/stream.rb +48 -37
- data/lib/io_streams/symmetric_encryption/reader.rb +6 -2
- data/lib/io_streams/symmetric_encryption/writer.rb +8 -4
- data/lib/io_streams/tabular/header.rb +49 -10
- data/lib/io_streams/tabular/parser/array.rb +0 -10
- data/lib/io_streams/tabular/parser/base.rb +10 -0
- data/lib/io_streams/tabular/parser/csv.rb +9 -36
- data/lib/io_streams/tabular/parser/fixed.rb +8 -6
- data/lib/io_streams/tabular/parser/psv.rb +6 -14
- data/lib/io_streams/tabular.rb +5 -10
- data/lib/io_streams/utils.rb +34 -2
- data/lib/io_streams/version.rb +1 -1
- data/lib/io_streams/writer.rb +16 -7
- data/lib/io_streams/xlsx/reader.rb +6 -2
- data/lib/io_streams/zip/reader.rb +4 -0
- data/lib/io_streams/zip/writer.rb +26 -10
- data/lib/iostreams.rb +0 -1
- metadata +46 -112
- data/lib/io_streams/deprecated.rb +0 -216
- data/lib/io_streams/tabular/utility/csv_row.rb +0 -105
- data/test/builder_test.rb +0 -311
- data/test/bzip2_reader_test.rb +0 -27
- data/test/bzip2_writer_test.rb +0 -56
- data/test/deprecated_test.rb +0 -121
- data/test/encode_reader_test.rb +0 -51
- data/test/encode_writer_test.rb +0 -90
- data/test/files/embedded_lines_test.csv +0 -7
- data/test/files/multiple_files.zip +0 -0
- data/test/files/spreadsheet.xlsx +0 -0
- data/test/files/test.csv +0 -4
- data/test/files/test.json +0 -3
- data/test/files/test.psv +0 -4
- data/test/files/text file.txt +0 -3
- data/test/files/text.txt +0 -3
- data/test/files/text.txt.bz2 +0 -0
- data/test/files/text.txt.gz +0 -0
- data/test/files/text.txt.gz.zip +0 -0
- data/test/files/text.zip +0 -0
- data/test/files/text.zip.gz +0 -0
- data/test/files/unclosed_quote_large_test.csv +0 -1658
- data/test/files/unclosed_quote_test.csv +0 -4
- data/test/files/unclosed_quote_test2.csv +0 -3
- data/test/gzip_reader_test.rb +0 -27
- data/test/gzip_writer_test.rb +0 -52
- data/test/io_streams_test.rb +0 -132
- data/test/line_reader_test.rb +0 -325
- data/test/line_writer_test.rb +0 -59
- data/test/minimal_file_reader.rb +0 -25
- data/test/path_test.rb +0 -55
- data/test/paths/file_test.rb +0 -213
- data/test/paths/http_test.rb +0 -34
- data/test/paths/matcher_test.rb +0 -120
- data/test/paths/s3_test.rb +0 -220
- data/test/paths/sftp_test.rb +0 -106
- data/test/pgp_reader_test.rb +0 -46
- data/test/pgp_test.rb +0 -267
- data/test/pgp_writer_test.rb +0 -130
- data/test/record_reader_test.rb +0 -60
- data/test/record_writer_test.rb +0 -82
- data/test/row_reader_test.rb +0 -35
- data/test/row_writer_test.rb +0 -56
- data/test/stream_test.rb +0 -577
- data/test/tabular_test.rb +0 -338
- data/test/test_helper.rb +0 -40
- data/test/utils_test.rb +0 -20
- data/test/xlsx_reader_test.rb +0 -37
- data/test/zip_reader_test.rb +0 -53
- data/test/zip_writer_test.rb +0 -48
|
@@ -71,7 +71,7 @@ module IOStreams
|
|
|
71
71
|
def render(row, header)
|
|
72
72
|
hash = header.to_hash(row)
|
|
73
73
|
|
|
74
|
-
result = ""
|
|
74
|
+
result = +""
|
|
75
75
|
layout.columns.each do |column|
|
|
76
76
|
result << column.render(hash[column.key], truncate)
|
|
77
77
|
end
|
|
@@ -93,7 +93,7 @@ module IOStreams
|
|
|
93
93
|
index = 0
|
|
94
94
|
layout.columns.each do |column|
|
|
95
95
|
if column.size == -1
|
|
96
|
-
hash[column.key] = column.parse(line[index
|
|
96
|
+
hash[column.key] = column.parse(line[index..]) if column.key
|
|
97
97
|
break
|
|
98
98
|
end
|
|
99
99
|
|
|
@@ -143,12 +143,13 @@ module IOStreams
|
|
|
143
143
|
|
|
144
144
|
class Column
|
|
145
145
|
TYPES = %i[string integer float].freeze
|
|
146
|
+
LINE_BREAK = /\r\n|\r|\n/
|
|
146
147
|
|
|
147
148
|
attr_reader :key, :size, :type, :decimals
|
|
148
149
|
|
|
149
150
|
def initialize(size:, key: nil, type: :string, decimals: 2)
|
|
150
151
|
@key = key
|
|
151
|
-
@size =
|
|
152
|
+
@size = [:remainder, "remainder"].include?(size) ? -1 : size.to_i
|
|
152
153
|
@type = type.to_sym
|
|
153
154
|
@decimals = decimals
|
|
154
155
|
|
|
@@ -167,9 +168,9 @@ module IOStreams
|
|
|
167
168
|
when :string
|
|
168
169
|
stripped_value
|
|
169
170
|
when :integer
|
|
170
|
-
stripped_value.
|
|
171
|
+
stripped_value.empty? ? nil : value.to_i
|
|
171
172
|
when :float
|
|
172
|
-
stripped_value.
|
|
173
|
+
stripped_value.empty? ? nil : value.to_f
|
|
173
174
|
else
|
|
174
175
|
raise(Errors::InvalidLayout, "Unsupported type: #{type.inspect}")
|
|
175
176
|
end
|
|
@@ -179,7 +180,8 @@ module IOStreams
|
|
|
179
180
|
formatted =
|
|
180
181
|
case type
|
|
181
182
|
when :string
|
|
182
|
-
value
|
|
183
|
+
# Replace line breaks with a space so that a value cannot add records.
|
|
184
|
+
value = value.to_s.gsub(LINE_BREAK, " ")
|
|
183
185
|
return value if size == -1
|
|
184
186
|
|
|
185
187
|
format(truncate ? "%-#{size}.#{size}s" : "%-#{size}s", value)
|
|
@@ -3,18 +3,7 @@ module IOStreams
|
|
|
3
3
|
module Parser
|
|
4
4
|
# For parsing a single line of Pipe-separated values
|
|
5
5
|
class Psv < Base
|
|
6
|
-
|
|
7
|
-
# Returns nil if the row is blank.
|
|
8
|
-
def parse_header(row)
|
|
9
|
-
return row if row.is_a?(::Array)
|
|
10
|
-
|
|
11
|
-
unless row.is_a?(String)
|
|
12
|
-
raise(IOStreams::Errors::InvalidHeader, "Format is :psv. Invalid input header: #{row.class.name}")
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
row.split("|")
|
|
16
|
-
end
|
|
17
|
-
|
|
6
|
+
LINE_BREAK = /\r\n|\r|\n/
|
|
18
7
|
# Returns [Array] the parsed PSV line
|
|
19
8
|
def parse(row)
|
|
20
9
|
return row if row.is_a?(::Array)
|
|
@@ -24,11 +13,14 @@ module IOStreams
|
|
|
24
13
|
row.split("|")
|
|
25
14
|
end
|
|
26
15
|
|
|
27
|
-
# Return the supplied array as a single line
|
|
16
|
+
# Return the supplied array as a single line PSV string.
|
|
17
|
+
#
|
|
18
|
+
# Since PSV has no escaping, any `|` within a value is replaced with `:`,
|
|
19
|
+
# and any line break with a space, so that a value cannot add columns or records.
|
|
28
20
|
def render(row, header)
|
|
29
21
|
array = header.to_array(row)
|
|
30
22
|
cleansed_array = array.collect do |i|
|
|
31
|
-
i.is_a?(String) ? i.tr("|", ":") : i
|
|
23
|
+
i.is_a?(String) ? i.tr("|", ":").gsub(LINE_BREAK, " ") : i
|
|
32
24
|
end
|
|
33
25
|
cleansed_array.join("|")
|
|
34
26
|
end
|
data/lib/io_streams/tabular.rb
CHANGED
|
@@ -40,10 +40,6 @@ module IOStreams
|
|
|
40
40
|
autoload :Psv, "io_streams/tabular/parser/psv"
|
|
41
41
|
end
|
|
42
42
|
|
|
43
|
-
module Utility
|
|
44
|
-
autoload :CSVRow, "io_streams/tabular/utility/csv_row"
|
|
45
|
-
end
|
|
46
|
-
|
|
47
43
|
attr_reader :format, :header, :parser
|
|
48
44
|
|
|
49
45
|
# Parse a delimited data source.
|
|
@@ -59,11 +55,10 @@ module IOStreams
|
|
|
59
55
|
# format_options: [Hash]
|
|
60
56
|
# Any specialized format specific options. For example, `:fixed` format requires the file definition.
|
|
61
57
|
#
|
|
62
|
-
# columns [Array<String>]
|
|
58
|
+
# columns [Array<String|Symbol>]
|
|
63
59
|
# The header columns when the file does not include a header row.
|
|
64
60
|
# Note:
|
|
65
|
-
#
|
|
66
|
-
# with MongoDB when it converts symbol keys to strings.
|
|
61
|
+
# Column names are converted to strings.
|
|
67
62
|
#
|
|
68
63
|
# allowed_columns [Array<String>]
|
|
69
64
|
# List of columns to allow.
|
|
@@ -91,7 +86,7 @@ module IOStreams
|
|
|
91
86
|
@header = Header.new(**args)
|
|
92
87
|
@format = file_name && format.nil? ? self.class.format_from_file_name(file_name) : format
|
|
93
88
|
@format ||= default_format
|
|
94
|
-
raise(UnknownFormat, "The format cannot be inferred from the file name: #{file_name}") unless @format
|
|
89
|
+
raise(Errors::UnknownFormat, "The format cannot be inferred from the file name: #{file_name}") unless @format
|
|
95
90
|
|
|
96
91
|
klass = self.class.parser_class(@format)
|
|
97
92
|
@parser = format_options ? klass.new(**format_options) : klass.new
|
|
@@ -177,7 +172,7 @@ module IOStreams
|
|
|
177
172
|
# Returns [Symbol] the format removed, or nil if the format was not registered
|
|
178
173
|
#
|
|
179
174
|
# Example:
|
|
180
|
-
#
|
|
175
|
+
# deregister_format(:psv)
|
|
181
176
|
def self.deregister_format(format)
|
|
182
177
|
raise(ArgumentError, "Invalid format #{format.inspect}") unless format.to_s =~ /\A\w+\Z/
|
|
183
178
|
|
|
@@ -200,7 +195,7 @@ module IOStreams
|
|
|
200
195
|
|
|
201
196
|
# Returns the parser class for the registered format.
|
|
202
197
|
def self.parser_class(format)
|
|
203
|
-
@formats[format
|
|
198
|
+
@formats[format&.to_sym] ||
|
|
204
199
|
raise(ArgumentError, "Unknown Tabular Format: #{format.inspect}")
|
|
205
200
|
end
|
|
206
201
|
|
data/lib/io_streams/utils.rb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
require "cgi"
|
|
1
2
|
require "uri"
|
|
2
3
|
require "tmpdir"
|
|
3
4
|
module IOStreams
|
|
@@ -11,11 +12,22 @@ module IOStreams
|
|
|
11
12
|
raise(LoadError, "Please install the gem '#{gem_name}' to support #{stream_type}. #{e.message}")
|
|
12
13
|
end
|
|
13
14
|
|
|
15
|
+
# Log a warning for options that a stream ignores, until they raise `ArgumentError` in v3.0.
|
|
16
|
+
def self.warn_unknown_options(unknown, stream, direction, valid)
|
|
17
|
+
return if unknown.empty?
|
|
18
|
+
|
|
19
|
+
names = unknown.keys.map(&:inspect).join(", ")
|
|
20
|
+
IOStreams.logger&.warn(
|
|
21
|
+
"Ignoring unknown #{unknown.size == 1 ? 'option' : 'options'} #{names} when #{direction} a #{stream.inspect} " \
|
|
22
|
+
"stream. Valid options: #{valid.map(&:inspect).join(', ')}. In v3.0 this will raise ArgumentError."
|
|
23
|
+
)
|
|
24
|
+
end
|
|
25
|
+
|
|
14
26
|
# Helper method: Returns [true|false] if a value is blank?
|
|
15
27
|
def self.blank?(value)
|
|
16
28
|
return true if value.nil?
|
|
17
29
|
return value !~ /\S/ if value.is_a?(String)
|
|
18
|
-
|
|
30
|
+
|
|
19
31
|
value.respond_to?(:empty?) ? value.empty? : !value
|
|
20
32
|
end
|
|
21
33
|
|
|
@@ -27,11 +39,31 @@ module IOStreams
|
|
|
27
39
|
::Dir::Tmpname.create([basename, extension], IOStreams.temp_dir, max_try: MAX_TEMP_FILE_NAME_ATTEMPTS) do |tmpname|
|
|
28
40
|
result = yield(tmpname)
|
|
29
41
|
ensure
|
|
30
|
-
::
|
|
42
|
+
::FileUtils.rm_f(tmpname)
|
|
31
43
|
end
|
|
32
44
|
result
|
|
33
45
|
end
|
|
34
46
|
|
|
47
|
+
# Yields the name of a new, empty temporary file that only the current user can read or write.
|
|
48
|
+
#
|
|
49
|
+
# The file is created exclusively, so that an existing file, or a link planted in a shared
|
|
50
|
+
# temp directory, is never written to. Only a name collision when creating the file is retried,
|
|
51
|
+
# and the file is only deleted once it was created here, so that another process's file is never removed.
|
|
52
|
+
#
|
|
53
|
+
# Returns the value from the block.
|
|
54
|
+
def self.private_temp_file(basename, extension = "")
|
|
55
|
+
file_name = ::Dir::Tmpname.create([basename, extension], IOStreams.temp_dir,
|
|
56
|
+
max_try: MAX_TEMP_FILE_NAME_ATTEMPTS) do |tmpname|
|
|
57
|
+
::File.open(tmpname, ::File::WRONLY | ::File::CREAT | ::File::EXCL, 0o600, &:close)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
begin
|
|
61
|
+
yield(file_name)
|
|
62
|
+
ensure
|
|
63
|
+
::FileUtils.rm_f(file_name)
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
35
67
|
class URI
|
|
36
68
|
attr_reader :scheme, :hostname, :path, :user, :password, :port, :query
|
|
37
69
|
|
data/lib/io_streams/version.rb
CHANGED
data/lib/io_streams/writer.rb
CHANGED
|
@@ -1,23 +1,32 @@
|
|
|
1
1
|
module IOStreams
|
|
2
2
|
class Writer
|
|
3
|
+
# Returns [Array<Symbol>] the names of the options this writer accepts,
|
|
4
|
+
# or [nil] when the writer does not declare them.
|
|
5
|
+
#
|
|
6
|
+
# When declared, `IOStreams::Builder` rejects any other option before the writer is opened,
|
|
7
|
+
# naming the direction an option belongs to when it is only valid for the other direction.
|
|
8
|
+
def self.option_names
|
|
9
|
+
nil
|
|
10
|
+
end
|
|
11
|
+
|
|
3
12
|
# When a Writer does not support streams, we copy the stream to a local temp file
|
|
4
13
|
# and then pass that filename in for this reader.
|
|
5
|
-
def self.stream(output_stream,
|
|
6
|
-
Utils.
|
|
7
|
-
count = file(file_name,
|
|
14
|
+
def self.stream(output_stream, **args, &block)
|
|
15
|
+
Utils.private_temp_file("iostreams_writer") do |file_name|
|
|
16
|
+
count = file(file_name, **args, &block)
|
|
8
17
|
::File.open(file_name, "rb") { |source| ::IO.copy_stream(source, output_stream) }
|
|
9
18
|
count
|
|
10
19
|
end
|
|
11
20
|
end
|
|
12
21
|
|
|
13
22
|
# When a Writer supports streams, also allow it to simply support a file
|
|
14
|
-
def self.file(file_name,
|
|
15
|
-
::File.open(file_name, "wb") { |file| stream(file,
|
|
23
|
+
def self.file(file_name, **args, &block)
|
|
24
|
+
::File.open(file_name, "wb") { |file| stream(file, **args, &block) }
|
|
16
25
|
end
|
|
17
26
|
|
|
18
27
|
# For processing by either a file name or an open IO stream.
|
|
19
|
-
def self.open(file_name_or_io, **args, &
|
|
20
|
-
file_name_or_io.is_a?(String) ? file(file_name_or_io, **args, &
|
|
28
|
+
def self.open(file_name_or_io, **args, &)
|
|
29
|
+
file_name_or_io.is_a?(String) ? file(file_name_or_io, **args, &) : stream(file_name_or_io, **args, &)
|
|
21
30
|
end
|
|
22
31
|
|
|
23
32
|
attr_reader :output_stream
|
|
@@ -3,10 +3,14 @@ require "csv"
|
|
|
3
3
|
module IOStreams
|
|
4
4
|
module Xlsx
|
|
5
5
|
class Reader < IOStreams::Reader
|
|
6
|
+
def self.option_names
|
|
7
|
+
[]
|
|
8
|
+
end
|
|
9
|
+
|
|
6
10
|
# Convert a xlsx, or xlsm file into CSV format.
|
|
7
|
-
def self.file(file_name,
|
|
11
|
+
def self.file(file_name, &block)
|
|
8
12
|
# Stream into a temp file as csv
|
|
9
|
-
Utils.
|
|
13
|
+
Utils.private_temp_file("iostreams_csv") do |temp_file_name|
|
|
10
14
|
::File.open(temp_file_name, "wb") { |io| new(file_name).each { |lines| io << lines.to_csv } }
|
|
11
15
|
::File.open(temp_file_name, "rb", &block)
|
|
12
16
|
end
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
module IOStreams
|
|
2
2
|
module Zip
|
|
3
3
|
class Reader < IOStreams::Reader
|
|
4
|
+
def self.option_names
|
|
5
|
+
%i[entry_file_name]
|
|
6
|
+
end
|
|
7
|
+
|
|
4
8
|
# Read from a zip file or stream, decompressing the contents as it is read
|
|
5
9
|
# The input stream from the first file found in the zip file is passed
|
|
6
10
|
# to the supplied block.
|
|
@@ -1,30 +1,46 @@
|
|
|
1
1
|
module IOStreams
|
|
2
2
|
module Zip
|
|
3
3
|
class Writer < IOStreams::Writer
|
|
4
|
+
def self.option_names
|
|
5
|
+
%i[zip_file_name entry_file_name]
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
# When writing to a file, default the entry name within the zip to the file name
|
|
9
|
+
# without the `.zip` extension, unless an entry name was explicitly supplied.
|
|
10
|
+
def self.file(file_name, zip_file_name: nil, entry_file_name: zip_file_name, &)
|
|
11
|
+
entry_file_name = file_name.to_s[0..-5] if entry_file_name.nil? && file_name.to_s =~ /\.zip\z/i
|
|
12
|
+
|
|
13
|
+
super(file_name, entry_file_name: entry_file_name, &)
|
|
14
|
+
end
|
|
15
|
+
|
|
4
16
|
# Write a single file in Zip format to the supplied output stream
|
|
5
17
|
#
|
|
6
18
|
# Parameters
|
|
7
19
|
# output_stream [IO]
|
|
8
20
|
# Output stream to write to
|
|
9
21
|
#
|
|
10
|
-
# original_file_name [String]
|
|
11
|
-
# Since this is a stream the original file name is used to create the entry_file_name if not supplied
|
|
12
|
-
#
|
|
13
22
|
# entry_file_name: [String]
|
|
14
23
|
# Name of the file entry within the Zip file.
|
|
24
|
+
# Default: "file"
|
|
15
25
|
#
|
|
16
26
|
# The stream supplied to the block only responds to #write
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
27
|
+
#
|
|
28
|
+
# Note:
|
|
29
|
+
# This writer uses `zip_kit` rather than `rubyzip` on purpose. `rubyzip`'s
|
|
30
|
+
# `Zip::OutputStream` requires a seekable output: it seeks back to rewrite each
|
|
31
|
+
# entry's local header with the CRC and sizes once the entry is finished. That
|
|
32
|
+
# means it cannot write directly to a non-seekable destination (S3, SFTP, HTTP,
|
|
33
|
+
# a socket); the output would first have to be spooled to a temporary file and
|
|
34
|
+
# then copied across. `zip_kit` streams to non-seekable outputs by emitting
|
|
35
|
+
# data descriptors instead, so we can write straight to the output stream and
|
|
36
|
+
# avoid the temp file round-trip.
|
|
37
|
+
def self.stream(output_stream, zip_file_name: nil, entry_file_name: zip_file_name)
|
|
22
38
|
entry_file_name ||= "file"
|
|
23
39
|
|
|
24
|
-
Utils.load_soft_dependency("
|
|
40
|
+
Utils.load_soft_dependency("zip_kit", "Zip") unless defined?(ZipKit::Streamer)
|
|
25
41
|
|
|
26
42
|
result = nil
|
|
27
|
-
|
|
43
|
+
ZipKit::Streamer.open(output_stream) do |zip|
|
|
28
44
|
zip.write_deflated_file(entry_file_name) { |io| result = yield(io) }
|
|
29
45
|
end
|
|
30
46
|
result
|
data/lib/iostreams.rb
CHANGED
metadata
CHANGED
|
@@ -1,17 +1,32 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: iostreams
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 2.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Reid Morrison
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
12
|
-
dependencies:
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: csv
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '0'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '0'
|
|
26
|
+
description: IOStreams makes file formats, compression (gzip, zip, bzip2), encryption
|
|
27
|
+
(PGP, symmetric), and storage location (local file, S3, SFTP, HTTP) transparent
|
|
28
|
+
to your application code. Files of any size are read and written one block at a
|
|
29
|
+
time, without loading the entire file into memory.
|
|
15
30
|
executables: []
|
|
16
31
|
extensions: []
|
|
17
32
|
extra_rdoc_files: []
|
|
@@ -19,10 +34,20 @@ files:
|
|
|
19
34
|
- LICENSE
|
|
20
35
|
- README.md
|
|
21
36
|
- Rakefile
|
|
37
|
+
- docs/CLAUDE.md
|
|
38
|
+
- docs/config.md
|
|
39
|
+
- docs/copy_files.md
|
|
40
|
+
- docs/extensions.md
|
|
41
|
+
- docs/formats.md
|
|
42
|
+
- docs/index.md
|
|
43
|
+
- docs/path.md
|
|
44
|
+
- docs/pgp.md
|
|
45
|
+
- docs/streams.md
|
|
46
|
+
- docs/tutorial.md
|
|
47
|
+
- docs/upgrading.md
|
|
22
48
|
- lib/io_streams/builder.rb
|
|
23
49
|
- lib/io_streams/bzip2/reader.rb
|
|
24
50
|
- lib/io_streams/bzip2/writer.rb
|
|
25
|
-
- lib/io_streams/deprecated.rb
|
|
26
51
|
- lib/io_streams/encode/reader.rb
|
|
27
52
|
- lib/io_streams/encode/writer.rb
|
|
28
53
|
- lib/io_streams/errors.rb
|
|
@@ -37,6 +62,7 @@ files:
|
|
|
37
62
|
- lib/io_streams/paths/matcher.rb
|
|
38
63
|
- lib/io_streams/paths/s3.rb
|
|
39
64
|
- lib/io_streams/paths/sftp.rb
|
|
65
|
+
- lib/io_streams/paths/sftp/net_ssh.rb
|
|
40
66
|
- lib/io_streams/pgp.rb
|
|
41
67
|
- lib/io_streams/pgp/reader.rb
|
|
42
68
|
- lib/io_streams/pgp/writer.rb
|
|
@@ -57,7 +83,6 @@ files:
|
|
|
57
83
|
- lib/io_streams/tabular/parser/hash.rb
|
|
58
84
|
- lib/io_streams/tabular/parser/json.rb
|
|
59
85
|
- lib/io_streams/tabular/parser/psv.rb
|
|
60
|
-
- lib/io_streams/tabular/utility/csv_row.rb
|
|
61
86
|
- lib/io_streams/utils.rb
|
|
62
87
|
- lib/io_streams/version.rb
|
|
63
88
|
- lib/io_streams/writer.rb
|
|
@@ -65,59 +90,16 @@ files:
|
|
|
65
90
|
- lib/io_streams/zip/reader.rb
|
|
66
91
|
- lib/io_streams/zip/writer.rb
|
|
67
92
|
- lib/iostreams.rb
|
|
68
|
-
|
|
69
|
-
- test/bzip2_reader_test.rb
|
|
70
|
-
- test/bzip2_writer_test.rb
|
|
71
|
-
- test/deprecated_test.rb
|
|
72
|
-
- test/encode_reader_test.rb
|
|
73
|
-
- test/encode_writer_test.rb
|
|
74
|
-
- test/files/embedded_lines_test.csv
|
|
75
|
-
- test/files/multiple_files.zip
|
|
76
|
-
- test/files/spreadsheet.xlsx
|
|
77
|
-
- test/files/test.csv
|
|
78
|
-
- test/files/test.json
|
|
79
|
-
- test/files/test.psv
|
|
80
|
-
- test/files/text file.txt
|
|
81
|
-
- test/files/text.txt
|
|
82
|
-
- test/files/text.txt.bz2
|
|
83
|
-
- test/files/text.txt.gz
|
|
84
|
-
- test/files/text.txt.gz.zip
|
|
85
|
-
- test/files/text.zip
|
|
86
|
-
- test/files/text.zip.gz
|
|
87
|
-
- test/files/unclosed_quote_large_test.csv
|
|
88
|
-
- test/files/unclosed_quote_test.csv
|
|
89
|
-
- test/files/unclosed_quote_test2.csv
|
|
90
|
-
- test/gzip_reader_test.rb
|
|
91
|
-
- test/gzip_writer_test.rb
|
|
92
|
-
- test/io_streams_test.rb
|
|
93
|
-
- test/line_reader_test.rb
|
|
94
|
-
- test/line_writer_test.rb
|
|
95
|
-
- test/minimal_file_reader.rb
|
|
96
|
-
- test/path_test.rb
|
|
97
|
-
- test/paths/file_test.rb
|
|
98
|
-
- test/paths/http_test.rb
|
|
99
|
-
- test/paths/matcher_test.rb
|
|
100
|
-
- test/paths/s3_test.rb
|
|
101
|
-
- test/paths/sftp_test.rb
|
|
102
|
-
- test/pgp_reader_test.rb
|
|
103
|
-
- test/pgp_test.rb
|
|
104
|
-
- test/pgp_writer_test.rb
|
|
105
|
-
- test/record_reader_test.rb
|
|
106
|
-
- test/record_writer_test.rb
|
|
107
|
-
- test/row_reader_test.rb
|
|
108
|
-
- test/row_writer_test.rb
|
|
109
|
-
- test/stream_test.rb
|
|
110
|
-
- test/tabular_test.rb
|
|
111
|
-
- test/test_helper.rb
|
|
112
|
-
- test/utils_test.rb
|
|
113
|
-
- test/xlsx_reader_test.rb
|
|
114
|
-
- test/zip_reader_test.rb
|
|
115
|
-
- test/zip_writer_test.rb
|
|
116
|
-
homepage: https://iostreams.rocketjob.io
|
|
93
|
+
homepage: https://iostreams.reidmorrison.com
|
|
117
94
|
licenses:
|
|
118
95
|
- Apache-2.0
|
|
119
|
-
metadata:
|
|
120
|
-
|
|
96
|
+
metadata:
|
|
97
|
+
bug_tracker_uri: https://github.com/reidmorrison/iostreams/issues
|
|
98
|
+
changelog_uri: https://github.com/reidmorrison/iostreams/blob/main/CHANGELOG.md
|
|
99
|
+
documentation_uri: https://iostreams.reidmorrison.com
|
|
100
|
+
homepage_uri: https://iostreams.reidmorrison.com
|
|
101
|
+
source_code_uri: https://github.com/reidmorrison/iostreams/tree/v2.1.0
|
|
102
|
+
rubygems_mfa_required: 'true'
|
|
121
103
|
rdoc_options: []
|
|
122
104
|
require_paths:
|
|
123
105
|
- lib
|
|
@@ -125,63 +107,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
125
107
|
requirements:
|
|
126
108
|
- - ">="
|
|
127
109
|
- !ruby/object:Gem::Version
|
|
128
|
-
version: '2
|
|
110
|
+
version: '3.2'
|
|
129
111
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
130
112
|
requirements:
|
|
131
113
|
- - ">="
|
|
132
114
|
- !ruby/object:Gem::Version
|
|
133
115
|
version: '0'
|
|
134
116
|
requirements: []
|
|
135
|
-
rubygems_version: 3.
|
|
136
|
-
signing_key:
|
|
117
|
+
rubygems_version: 3.6.9
|
|
137
118
|
specification_version: 4
|
|
138
|
-
summary:
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
- test/bzip2_reader_test.rb
|
|
142
|
-
- test/bzip2_writer_test.rb
|
|
143
|
-
- test/deprecated_test.rb
|
|
144
|
-
- test/encode_reader_test.rb
|
|
145
|
-
- test/encode_writer_test.rb
|
|
146
|
-
- test/files/embedded_lines_test.csv
|
|
147
|
-
- test/files/multiple_files.zip
|
|
148
|
-
- test/files/spreadsheet.xlsx
|
|
149
|
-
- test/files/test.csv
|
|
150
|
-
- test/files/test.json
|
|
151
|
-
- test/files/test.psv
|
|
152
|
-
- test/files/text file.txt
|
|
153
|
-
- test/files/text.txt
|
|
154
|
-
- test/files/text.txt.bz2
|
|
155
|
-
- test/files/text.txt.gz
|
|
156
|
-
- test/files/text.txt.gz.zip
|
|
157
|
-
- test/files/text.zip
|
|
158
|
-
- test/files/text.zip.gz
|
|
159
|
-
- test/files/unclosed_quote_large_test.csv
|
|
160
|
-
- test/files/unclosed_quote_test.csv
|
|
161
|
-
- test/files/unclosed_quote_test2.csv
|
|
162
|
-
- test/gzip_reader_test.rb
|
|
163
|
-
- test/gzip_writer_test.rb
|
|
164
|
-
- test/io_streams_test.rb
|
|
165
|
-
- test/line_reader_test.rb
|
|
166
|
-
- test/line_writer_test.rb
|
|
167
|
-
- test/minimal_file_reader.rb
|
|
168
|
-
- test/path_test.rb
|
|
169
|
-
- test/paths/file_test.rb
|
|
170
|
-
- test/paths/http_test.rb
|
|
171
|
-
- test/paths/matcher_test.rb
|
|
172
|
-
- test/paths/s3_test.rb
|
|
173
|
-
- test/paths/sftp_test.rb
|
|
174
|
-
- test/pgp_reader_test.rb
|
|
175
|
-
- test/pgp_test.rb
|
|
176
|
-
- test/pgp_writer_test.rb
|
|
177
|
-
- test/record_reader_test.rb
|
|
178
|
-
- test/record_writer_test.rb
|
|
179
|
-
- test/row_reader_test.rb
|
|
180
|
-
- test/row_writer_test.rb
|
|
181
|
-
- test/stream_test.rb
|
|
182
|
-
- test/tabular_test.rb
|
|
183
|
-
- test/test_helper.rb
|
|
184
|
-
- test/utils_test.rb
|
|
185
|
-
- test/xlsx_reader_test.rb
|
|
186
|
-
- test/zip_reader_test.rb
|
|
187
|
-
- test/zip_writer_test.rb
|
|
119
|
+
summary: 'Streaming I/O for Ruby: compression, encryption, file format, and storage
|
|
120
|
+
location transparent to your code.'
|
|
121
|
+
test_files: []
|