iostreams 1.6.2 → 1.7.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/lib/io_streams/builder.rb +4 -2
- data/lib/io_streams/line/reader.rb +6 -6
- data/lib/io_streams/paths/s3.rb +22 -14
- data/lib/io_streams/paths/sftp.rb +87 -59
- data/lib/io_streams/pgp.rb +15 -15
- data/lib/io_streams/pgp/writer.rb +1 -2
- data/lib/io_streams/stream.rb +20 -10
- data/lib/io_streams/tabular/parser/fixed.rb +1 -1
- data/lib/io_streams/utils.rb +3 -5
- data/lib/io_streams/version.rb +1 -1
- data/lib/iostreams.rb +8 -0
- data/test/paths/file_test.rb +6 -8
- data/test/paths/sftp_test.rb +7 -1
- data/test/stream_test.rb +5 -5
- data/test/test_helper.rb +0 -3
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 849ceda63eb30f95762a7c985cd215d424e62afd68ab20776e8d16c188dd6aed
|
4
|
+
data.tar.gz: 8e26af86c40bb673ce36855a7fb30d1c4b401edc3eac0b27a71b9760cfe865dd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 99318c4c64e0133df57b84429b1c2f9caa064abb1405ace5d55208e41b6bf8bb8fa83a75db8ae46d53753f10d566bab53971d95871ed4011bab4571d31bebe8a
|
7
|
+
data.tar.gz: bfba3a033c753e3fe05f798177b8f3c7ee8f566eabaf9223984fa902b288cb3515154f621a4e97f75b6c5bc31da88f284390c2d82c5015d7682ecf08c2a671d3
|
data/lib/io_streams/builder.rb
CHANGED
@@ -97,7 +97,9 @@ module IOStreams
|
|
97
97
|
end
|
98
98
|
|
99
99
|
def format=(format)
|
100
|
-
|
100
|
+
unless format.nil? || IOStreams::Tabular.registered_formats.include?(format)
|
101
|
+
raise(ArgumentError, "Invalid format: #{format.inspect}")
|
102
|
+
end
|
101
103
|
|
102
104
|
@format = format
|
103
105
|
end
|
@@ -106,7 +108,7 @@ module IOStreams
|
|
106
108
|
|
107
109
|
def class_for_stream(type, stream)
|
108
110
|
ext = IOStreams.extensions[stream.nil? ? nil : stream.to_sym] ||
|
109
|
-
|
111
|
+
raise(ArgumentError, "Unknown Stream type: #{stream.inspect}")
|
110
112
|
ext.send("#{type}_class") || raise(ArgumentError, "No #{type} registered for Stream type: #{stream.inspect}")
|
111
113
|
end
|
112
114
|
|
@@ -96,17 +96,17 @@ module IOStreams
|
|
96
96
|
while line.count(@embedded_within).odd?
|
97
97
|
if eof? || line.length > @buffer_size * 10
|
98
98
|
raise(Errors::MalformedDataError.new(
|
99
|
-
|
100
|
-
|
101
|
-
|
99
|
+
"Unbalanced delimited field, delimiter: #{@embedded_within}",
|
100
|
+
initial_line_number
|
101
|
+
))
|
102
102
|
end
|
103
103
|
line << @delimiter
|
104
104
|
next_line = _readline
|
105
105
|
if next_line.nil?
|
106
106
|
raise(Errors::MalformedDataError.new(
|
107
|
-
|
108
|
-
|
109
|
-
|
107
|
+
"Unbalanced delimited field, delimiter: #{@embedded_within}",
|
108
|
+
initial_line_number
|
109
|
+
))
|
110
110
|
end
|
111
111
|
line << next_line
|
112
112
|
end
|
data/lib/io_streams/paths/s3.rb
CHANGED
@@ -3,7 +3,7 @@ require "uri"
|
|
3
3
|
module IOStreams
|
4
4
|
module Paths
|
5
5
|
class S3 < IOStreams::Path
|
6
|
-
attr_reader :bucket_name, :
|
6
|
+
attr_reader :bucket_name, :options
|
7
7
|
|
8
8
|
# Largest file size supported by the S3 copy object api.
|
9
9
|
S3_COPY_OBJECT_SIZE_LIMIT = 5 * 1024 * 1024 * 1024
|
@@ -141,16 +141,17 @@ module IOStreams
|
|
141
141
|
|
142
142
|
@bucket_name = uri.hostname
|
143
143
|
key = uri.path.sub(%r{\A/}, "")
|
144
|
-
|
145
|
-
|
146
|
-
client
|
147
|
-
@client = ::Aws::S3::Client.new(client)
|
144
|
+
|
145
|
+
if client && !client.is_a?(Hash)
|
146
|
+
@client = client
|
148
147
|
else
|
149
|
-
@
|
148
|
+
@client_options = client.is_a?(Hash) ? client.dup : {}
|
149
|
+
@client_options[:access_key_id] = access_key_id if access_key_id
|
150
|
+
@client_options[:secret_access_key] = secret_access_key if secret_access_key
|
150
151
|
end
|
151
|
-
@options = args
|
152
152
|
|
153
|
-
@options
|
153
|
+
@options = args
|
154
|
+
@options.merge!(uri.query.transform_keys(&:to_sym)) if uri.query
|
154
155
|
|
155
156
|
super(key)
|
156
157
|
end
|
@@ -190,11 +191,11 @@ module IOStreams
|
|
190
191
|
end
|
191
192
|
|
192
193
|
# Make S3 perform direct copies within S3 itself.
|
193
|
-
def copy_to(target_path, convert: true)
|
194
|
-
return super(target_path) if convert || (size.to_i >= S3_COPY_OBJECT_SIZE_LIMIT)
|
194
|
+
def copy_to(target_path, convert: true, **args)
|
195
|
+
return super(target_path, convert: convert, **args) if convert || (size.to_i >= S3_COPY_OBJECT_SIZE_LIMIT)
|
195
196
|
|
196
197
|
target = IOStreams.new(target_path)
|
197
|
-
return super(target) unless target.is_a?(self.class)
|
198
|
+
return super(target, convert: convert, **args) unless target.is_a?(self.class)
|
198
199
|
|
199
200
|
source_name = ::File.join(bucket_name, path)
|
200
201
|
client.copy_object(options.merge(bucket: target.bucket_name, key: target.path, copy_source: source_name))
|
@@ -202,11 +203,13 @@ module IOStreams
|
|
202
203
|
end
|
203
204
|
|
204
205
|
# Make S3 perform direct copies within S3 itself.
|
205
|
-
def copy_from(source_path, convert: true)
|
206
|
-
return super(source_path) if convert
|
206
|
+
def copy_from(source_path, convert: true, **args)
|
207
|
+
return super(source_path, convert: true, **args) if convert
|
207
208
|
|
208
209
|
source = IOStreams.new(source_path)
|
209
|
-
|
210
|
+
if !source.is_a?(self.class) || (source.size.to_i >= S3_COPY_OBJECT_SIZE_LIMIT)
|
211
|
+
return super(source, convert: convert, **args)
|
212
|
+
end
|
210
213
|
|
211
214
|
source_name = ::File.join(source.bucket_name, source.path)
|
212
215
|
client.copy_object(options.merge(bucket: bucket_name, key: path, copy_source: source_name))
|
@@ -312,6 +315,11 @@ module IOStreams
|
|
312
315
|
def partial_files_visible?
|
313
316
|
false
|
314
317
|
end
|
318
|
+
|
319
|
+
# Lazy load S3 client since it takes two seconds to create itself!
|
320
|
+
def client
|
321
|
+
@client ||= ::Aws::S3::Client.new(@client_options)
|
322
|
+
end
|
315
323
|
end
|
316
324
|
end
|
317
325
|
end
|
@@ -47,9 +47,23 @@ module IOStreams
|
|
47
47
|
# password: [String]
|
48
48
|
# Password for the user.
|
49
49
|
#
|
50
|
-
#
|
51
|
-
#
|
52
|
-
#
|
50
|
+
# ssh_options: [Hash]
|
51
|
+
# - IdentityKey [String]
|
52
|
+
# The identity key that this client should use to talk to this host.
|
53
|
+
# Under the covers this value is written to a file and then the file name is passed as `IdentityFile`
|
54
|
+
# - HostKey [String]
|
55
|
+
# The expected SSH Host key that is presented by the remote host.
|
56
|
+
# Instead of storing the host key in the `known_hosts` file, it can be supplied explicity
|
57
|
+
# using this option.
|
58
|
+
# Under the covers this value is written to a file and then the file name is passed as `UserKnownHostsFile`
|
59
|
+
# Notes:
|
60
|
+
# - It must contain the entire line that would be stored in `known_hosts`,
|
61
|
+
# including the hostname, ip address, key type and key value. This value is written as-is into a
|
62
|
+
# "known_hosts" like file and then passed into sftp using the `UserKnownHostsFile` option.
|
63
|
+
# - The easiest way to generate the required is to use `ssh-keyscan` and then supply that value in this field.
|
64
|
+
# For example: `ssh-keyscan hostname`
|
65
|
+
# - Any other options supported by ssh_config.
|
66
|
+
# `man ssh_config` to see all available options.
|
53
67
|
#
|
54
68
|
# Examples:
|
55
69
|
#
|
@@ -168,38 +182,36 @@ module IOStreams
|
|
168
182
|
def sftp_download(remote_file_name, local_file_name)
|
169
183
|
with_sftp_args do |args|
|
170
184
|
Open3.popen2e(*args) do |writer, reader, waith_thr|
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
unless waith_thr.value.success?
|
185
|
-
raise(
|
186
|
-
Errors::CommunicationsFailure,
|
187
|
-
"Download failed calling #{self.class.sftp_bin} via #{self.class.sshpass_bin}: #{out}"
|
188
|
-
)
|
189
|
-
end
|
190
|
-
|
191
|
-
out
|
192
|
-
rescue Errno::EPIPE
|
193
|
-
out = begin
|
194
|
-
reader.read.chomp
|
195
|
-
rescue StandardError
|
196
|
-
nil
|
197
|
-
end
|
185
|
+
# Give time for remote sftp server to get ready to accept the password.
|
186
|
+
sleep self.class.before_password_wait_seconds
|
187
|
+
|
188
|
+
writer.puts password
|
189
|
+
|
190
|
+
# Give time for password to be processed and stdin to be passed to sftp process.
|
191
|
+
sleep self.class.sshpass_wait_seconds
|
192
|
+
|
193
|
+
writer.puts "get #{remote_file_name} #{local_file_name}"
|
194
|
+
writer.puts "bye"
|
195
|
+
writer.close
|
196
|
+
out = reader.read.chomp
|
197
|
+
unless waith_thr.value.success?
|
198
198
|
raise(
|
199
199
|
Errors::CommunicationsFailure,
|
200
200
|
"Download failed calling #{self.class.sftp_bin} via #{self.class.sshpass_bin}: #{out}"
|
201
201
|
)
|
202
202
|
end
|
203
|
+
|
204
|
+
out
|
205
|
+
rescue Errno::EPIPE
|
206
|
+
out = begin
|
207
|
+
reader.read.chomp
|
208
|
+
rescue StandardError
|
209
|
+
nil
|
210
|
+
end
|
211
|
+
raise(
|
212
|
+
Errors::CommunicationsFailure,
|
213
|
+
"Download failed calling #{self.class.sftp_bin} via #{self.class.sshpass_bin}: #{out}"
|
214
|
+
)
|
203
215
|
end
|
204
216
|
end
|
205
217
|
end
|
@@ -207,48 +219,64 @@ module IOStreams
|
|
207
219
|
def sftp_upload(local_file_name, remote_file_name)
|
208
220
|
with_sftp_args do |args|
|
209
221
|
Open3.popen2e(*args) do |writer, reader, waith_thr|
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
unless waith_thr.value.success?
|
219
|
-
raise(
|
220
|
-
Errors::CommunicationsFailure,
|
221
|
-
"Upload failed calling #{self.class.sftp_bin} via #{self.class.sshpass_bin}: #{out}"
|
222
|
-
)
|
223
|
-
end
|
224
|
-
|
225
|
-
out
|
226
|
-
rescue Errno::EPIPE
|
227
|
-
out = begin
|
228
|
-
reader.read.chomp
|
229
|
-
rescue StandardError
|
230
|
-
nil
|
231
|
-
end
|
222
|
+
writer.puts(password) if password
|
223
|
+
# Give time for password to be processed and stdin to be passed to sftp process.
|
224
|
+
sleep self.class.sshpass_wait_seconds
|
225
|
+
writer.puts "put #{local_file_name.inspect} #{remote_file_name.inspect}"
|
226
|
+
writer.puts "bye"
|
227
|
+
writer.close
|
228
|
+
out = reader.read.chomp
|
229
|
+
unless waith_thr.value.success?
|
232
230
|
raise(
|
233
231
|
Errors::CommunicationsFailure,
|
234
232
|
"Upload failed calling #{self.class.sftp_bin} via #{self.class.sshpass_bin}: #{out}"
|
235
233
|
)
|
236
234
|
end
|
235
|
+
|
236
|
+
out
|
237
|
+
rescue Errno::EPIPE
|
238
|
+
out = begin
|
239
|
+
reader.read.chomp
|
240
|
+
rescue StandardError
|
241
|
+
nil
|
242
|
+
end
|
243
|
+
raise(
|
244
|
+
Errors::CommunicationsFailure,
|
245
|
+
"Upload failed calling #{self.class.sftp_bin} via #{self.class.sshpass_bin}: #{out}"
|
246
|
+
)
|
237
247
|
end
|
238
248
|
end
|
239
249
|
end
|
240
250
|
|
241
251
|
def with_sftp_args
|
242
|
-
return yield sftp_args(ssh_options)
|
252
|
+
return yield sftp_args(ssh_options) if !ssh_options.key?("IdentityKey") && !ssh_options.key?("HostKey")
|
253
|
+
|
254
|
+
with_identity_key(ssh_options.dup) do |options|
|
255
|
+
with_host_key(options) do |options2|
|
256
|
+
yield sftp_args(options2)
|
257
|
+
end
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
def with_identity_key(options)
|
262
|
+
return yield options unless ssh_options.key?("IdentityKey")
|
263
|
+
|
264
|
+
with_temp_file(options, "IdentityFile", options.delete("IdentityKey")) { yield options }
|
265
|
+
end
|
266
|
+
|
267
|
+
def with_host_key(options)
|
268
|
+
return yield options unless ssh_options.key?("HostKey")
|
269
|
+
|
270
|
+
with_temp_file(options, "UserKnownHostsFile", options.delete("HostKey")) { yield options }
|
271
|
+
end
|
243
272
|
|
273
|
+
def with_temp_file(options, option, value)
|
244
274
|
Utils.temp_file_name("iostreams-sftp-args", "key") do |file_name|
|
245
|
-
options = ssh_options.dup
|
246
|
-
key = options.delete("IdentityKey")
|
247
275
|
# sftp requires that private key is only readable by the current user
|
248
|
-
::File.open(file_name, "wb", 0o600) { |io| io.write(
|
276
|
+
::File.open(file_name, "wb", 0o600) { |io| io.write(value) }
|
249
277
|
|
250
|
-
options[
|
251
|
-
yield
|
278
|
+
options[option] = file_name
|
279
|
+
yield options
|
252
280
|
end
|
253
281
|
end
|
254
282
|
|
@@ -277,7 +305,7 @@ module IOStreams
|
|
277
305
|
end
|
278
306
|
|
279
307
|
def build_ssh_options
|
280
|
-
options
|
308
|
+
options = ssh_options.dup
|
281
309
|
options[:logger] ||= logger if defined?(SemanticLogger)
|
282
310
|
options[:port] ||= port
|
283
311
|
options[:max_pkt_size] ||= 65_536
|
data/lib/io_streams/pgp.rb
CHANGED
@@ -48,8 +48,8 @@ module IOStreams
|
|
48
48
|
# See `man gpg` for the remaining options
|
49
49
|
def self.generate_key(name:,
|
50
50
|
email:,
|
51
|
-
comment: nil,
|
52
51
|
passphrase:,
|
52
|
+
comment: nil,
|
53
53
|
key_type: "RSA",
|
54
54
|
key_length: 4096,
|
55
55
|
subkey_type: "RSA",
|
@@ -291,10 +291,8 @@ module IOStreams
|
|
291
291
|
version_check
|
292
292
|
Open3.popen2e("#{executable} --list-keys --fingerprint --with-colons #{email}") do |_stdin, out, waith_thr|
|
293
293
|
output = out.read.chomp
|
294
|
-
|
295
|
-
|
296
|
-
raise(Pgp::Failure, "GPG Failed calling #{executable} to list keys for #{email}: #{output}")
|
297
|
-
end
|
294
|
+
if !waith_thr.value.success? && !(output !~ /(public key not found|No public key)/i)
|
295
|
+
raise(Pgp::Failure, "GPG Failed calling #{executable} to list keys for #{email}: #{output}")
|
298
296
|
end
|
299
297
|
|
300
298
|
output.each_line do |line|
|
@@ -336,9 +334,11 @@ module IOStreams
|
|
336
334
|
match[1]
|
337
335
|
end
|
338
336
|
else
|
339
|
-
|
337
|
+
if err !~ /(key not found|No (public|secret) key)/i
|
338
|
+
raise(Pgp::Failure, "GPG Failed calling #{executable} to list keys for #{email || key_id}: #{err}#{out}")
|
339
|
+
end
|
340
340
|
|
341
|
-
|
341
|
+
[]
|
342
342
|
end
|
343
343
|
end
|
344
344
|
end
|
@@ -382,10 +382,10 @@ module IOStreams
|
|
382
382
|
key_length: match[3].to_s.to_i,
|
383
383
|
key_type: match[2],
|
384
384
|
date: (begin
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
385
|
+
Date.parse(match[4].to_s)
|
386
|
+
rescue StandardError
|
387
|
+
match[4]
|
388
|
+
end)
|
389
389
|
}
|
390
390
|
elsif (match = line.match(%r{(pub|sec)\s+(\d+)(.*)/(\w+)\s+(\d+-\d+-\d+)(\s+(.+)<(.+)>)?}))
|
391
391
|
# Matches: pub 2048R/C7F9D9CB 2016-10-26
|
@@ -396,10 +396,10 @@ module IOStreams
|
|
396
396
|
key_type: match[3],
|
397
397
|
key_id: match[4],
|
398
398
|
date: (begin
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
399
|
+
Date.parse(match[5].to_s)
|
400
|
+
rescue StandardError
|
401
|
+
match[5]
|
402
|
+
end)
|
403
403
|
}
|
404
404
|
# Prior to gpg v2.0.30
|
405
405
|
if match[7]
|
data/lib/io_streams/stream.rb
CHANGED
@@ -151,6 +151,9 @@ module IOStreams
|
|
151
151
|
# Whether to apply the stream conversions during the copy.
|
152
152
|
# Default: true
|
153
153
|
#
|
154
|
+
# :mode [:line, :array, :hash]
|
155
|
+
# When convert is `true` then use this mode to convert the contents of the file.
|
156
|
+
#
|
154
157
|
# Examples:
|
155
158
|
#
|
156
159
|
# # Copy and convert streams based on file extensions
|
@@ -162,11 +165,17 @@ module IOStreams
|
|
162
165
|
# # Advanced copy with custom stream conversions on source and target.
|
163
166
|
# source = IOStreams.path("source_file").stream(encoding: "BINARY")
|
164
167
|
# IOStreams.path("target_file.pgp").option(:pgp, passphrase: "hello").copy_from(source)
|
165
|
-
def copy_from(source, convert: true)
|
168
|
+
def copy_from(source, convert: true, mode: nil, **args)
|
166
169
|
if convert
|
167
170
|
stream = IOStreams.new(source)
|
168
|
-
|
169
|
-
|
171
|
+
if mode
|
172
|
+
writer(mode, **args) do |target|
|
173
|
+
stream.each(mode) { |row| target << row }
|
174
|
+
end
|
175
|
+
else
|
176
|
+
writer(**args) do |target|
|
177
|
+
stream.reader { |src| IO.copy_stream(src, target) }
|
178
|
+
end
|
170
179
|
end
|
171
180
|
else
|
172
181
|
stream = source.is_a?(Stream) ? source.dup : IOStreams.new(source)
|
@@ -176,9 +185,9 @@ module IOStreams
|
|
176
185
|
end
|
177
186
|
end
|
178
187
|
|
179
|
-
def copy_to(target,
|
188
|
+
def copy_to(target, **args)
|
180
189
|
target = IOStreams.new(target)
|
181
|
-
target.copy_from(self,
|
190
|
+
target.copy_from(self, **args)
|
182
191
|
end
|
183
192
|
|
184
193
|
# Set/get the original file_name
|
@@ -365,8 +374,8 @@ module IOStreams
|
|
365
374
|
IOStreams::Row::Writer.stream(
|
366
375
|
io,
|
367
376
|
original_file_name: builder.file_name,
|
368
|
-
format:
|
369
|
-
format_options:
|
377
|
+
format: builder.format,
|
378
|
+
format_options: builder.format_options,
|
370
379
|
**args,
|
371
380
|
&block
|
372
381
|
)
|
@@ -380,10 +389,11 @@ module IOStreams
|
|
380
389
|
IOStreams::Record::Writer.stream(
|
381
390
|
io,
|
382
391
|
original_file_name: builder.file_name,
|
383
|
-
format:
|
384
|
-
format_options:
|
392
|
+
format: builder.format,
|
393
|
+
format_options: builder.format_options,
|
385
394
|
**args,
|
386
|
-
&block
|
395
|
+
&block
|
396
|
+
)
|
387
397
|
end
|
388
398
|
end
|
389
399
|
end
|
@@ -146,7 +146,7 @@ module IOStreams
|
|
146
146
|
|
147
147
|
attr_reader :key, :size, :type, :decimals
|
148
148
|
|
149
|
-
def initialize(key: nil,
|
149
|
+
def initialize(size:, key: nil, type: :string, decimals: 2)
|
150
150
|
@key = key
|
151
151
|
@size = size == :remainder ? -1 : size.to_i
|
152
152
|
@type = type.to_sym
|
data/lib/io_streams/utils.rb
CHANGED
@@ -28,11 +28,9 @@ module IOStreams
|
|
28
28
|
def self.temp_file_name(basename, extension = "")
|
29
29
|
result = nil
|
30
30
|
::Dir::Tmpname.create([basename, extension], IOStreams.temp_dir, max_try: MAX_TEMP_FILE_NAME_ATTEMPTS) do |tmpname|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
::File.unlink(tmpname) if ::File.exist?(tmpname)
|
35
|
-
end
|
31
|
+
result = yield(tmpname)
|
32
|
+
ensure
|
33
|
+
::File.unlink(tmpname) if ::File.exist?(tmpname)
|
36
34
|
end
|
37
35
|
result
|
38
36
|
end
|
data/lib/io_streams/version.rb
CHANGED
data/lib/iostreams.rb
CHANGED
@@ -23,33 +23,41 @@ module IOStreams
|
|
23
23
|
autoload :Reader, "io_streams/bzip2/reader"
|
24
24
|
autoload :Writer, "io_streams/bzip2/writer"
|
25
25
|
end
|
26
|
+
|
26
27
|
module Encode
|
27
28
|
autoload :Reader, "io_streams/encode/reader"
|
28
29
|
autoload :Writer, "io_streams/encode/writer"
|
29
30
|
end
|
31
|
+
|
30
32
|
module Gzip
|
31
33
|
autoload :Reader, "io_streams/gzip/reader"
|
32
34
|
autoload :Writer, "io_streams/gzip/writer"
|
33
35
|
end
|
36
|
+
|
34
37
|
module Line
|
35
38
|
autoload :Reader, "io_streams/line/reader"
|
36
39
|
autoload :Writer, "io_streams/line/writer"
|
37
40
|
end
|
41
|
+
|
38
42
|
module Record
|
39
43
|
autoload :Reader, "io_streams/record/reader"
|
40
44
|
autoload :Writer, "io_streams/record/writer"
|
41
45
|
end
|
46
|
+
|
42
47
|
module Row
|
43
48
|
autoload :Reader, "io_streams/row/reader"
|
44
49
|
autoload :Writer, "io_streams/row/writer"
|
45
50
|
end
|
51
|
+
|
46
52
|
module SymmetricEncryption
|
47
53
|
autoload :Reader, "io_streams/symmetric_encryption/reader"
|
48
54
|
autoload :Writer, "io_streams/symmetric_encryption/writer"
|
49
55
|
end
|
56
|
+
|
50
57
|
module Xlsx
|
51
58
|
autoload :Reader, "io_streams/xlsx/reader"
|
52
59
|
end
|
60
|
+
|
53
61
|
module Zip
|
54
62
|
autoload :Reader, "io_streams/zip/reader"
|
55
63
|
autoload :Writer, "io_streams/zip/writer"
|
data/test/paths/file_test.rb
CHANGED
@@ -126,15 +126,13 @@ module Paths
|
|
126
126
|
|
127
127
|
it "missing source file" do
|
128
128
|
IOStreams.temp_file("iostreams_move_test", ".txt") do |temp_file|
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
temp_file.move_to(target)
|
134
|
-
end
|
135
|
-
refute target.exist?
|
136
|
-
refute temp_file.exist?
|
129
|
+
refute temp_file.exist?
|
130
|
+
target = temp_file.directory.join("move_test.txt")
|
131
|
+
assert_raises Errno::ENOENT do
|
132
|
+
temp_file.move_to(target)
|
137
133
|
end
|
134
|
+
refute target.exist?
|
135
|
+
refute temp_file.exist?
|
138
136
|
end
|
139
137
|
end
|
140
138
|
|
data/test/paths/sftp_test.rb
CHANGED
@@ -20,7 +20,13 @@ module Paths
|
|
20
20
|
let(:file_name) { File.join(File.dirname(__FILE__), "..", "files", "text file.txt") }
|
21
21
|
let(:raw) { File.read(file_name) }
|
22
22
|
|
23
|
-
let(:root_path)
|
23
|
+
let(:root_path) do
|
24
|
+
if ENV["SFTP_HOST_KEY"]
|
25
|
+
IOStreams::Paths::SFTP.new(url, username: username, password: password, ssh_options: {"HostKey" => ENV["SFTP_HOST_KEY"]})
|
26
|
+
else
|
27
|
+
IOStreams::Paths::SFTP.new(url, username: username, password: password)
|
28
|
+
end
|
29
|
+
end
|
24
30
|
|
25
31
|
let :existing_path do
|
26
32
|
path = root_path.join("test.txt")
|
data/test/stream_test.rb
CHANGED
@@ -45,9 +45,9 @@ class StreamTest < Minitest::Test
|
|
45
45
|
it "reads a zip file" do
|
46
46
|
File.open(multiple_zip_file_name, "rb") do |io|
|
47
47
|
result = IOStreams::Stream.new(io).
|
48
|
-
|
49
|
-
|
50
|
-
|
48
|
+
file_name(multiple_zip_file_name).
|
49
|
+
option(:zip, entry_file_name: "test.json").
|
50
|
+
read
|
51
51
|
assert_equal contents_test_json, result
|
52
52
|
end
|
53
53
|
end
|
@@ -55,8 +55,8 @@ class StreamTest < Minitest::Test
|
|
55
55
|
it "reads a zip file from within a gz file" do
|
56
56
|
File.open(zip_gz_file_name, "rb") do |io|
|
57
57
|
result = IOStreams::Stream.new(io).
|
58
|
-
|
59
|
-
|
58
|
+
file_name(zip_gz_file_name).
|
59
|
+
read
|
60
60
|
assert_equal contents_test_txt, result
|
61
61
|
end
|
62
62
|
end
|
data/test/test_helper.rb
CHANGED
@@ -2,7 +2,6 @@ $LOAD_PATH.unshift File.dirname(__FILE__) + "/../lib"
|
|
2
2
|
|
3
3
|
require "yaml"
|
4
4
|
require "minitest/autorun"
|
5
|
-
require "minitest/reporters"
|
6
5
|
require "iostreams"
|
7
6
|
require "amazing_print"
|
8
7
|
require "symmetric-encryption"
|
@@ -10,8 +9,6 @@ require "symmetric-encryption"
|
|
10
9
|
# Since PGP libraries use UTC for Dates
|
11
10
|
ENV["TZ"] = "UTC"
|
12
11
|
|
13
|
-
Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new
|
14
|
-
|
15
12
|
# Test cipher
|
16
13
|
SymmetricEncryption.cipher = SymmetricEncryption::Cipher.new(
|
17
14
|
cipher_name: "aes-128-cbc",
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: iostreams
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Reid Morrison
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-06-23 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description:
|
14
14
|
email:
|
@@ -125,7 +125,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
125
125
|
requirements:
|
126
126
|
- - ">="
|
127
127
|
- !ruby/object:Gem::Version
|
128
|
-
version: '2.
|
128
|
+
version: '2.5'
|
129
129
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
130
130
|
requirements:
|
131
131
|
- - ">="
|