iostreams 0.20.1 → 0.20.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d2c3b941a898cf14f2e8d5ac430f55efc602126f0d2e339014cb3de97d7c9233
4
- data.tar.gz: e5745a12f24746ecf624627ac45e900251b0c3b83b109d7f18c04ffaf4efeba5
3
+ metadata.gz: f09dde2bcb517dd7c24e6bdf7bdfcfe313b2c5a17f3c8b1ac6caf850d1057364
4
+ data.tar.gz: 8886732d0a04007205ac6b0f76aede0efc4617dc5fae51f06d9d9a4f5420fdb9
5
5
  SHA512:
6
- metadata.gz: ae879c20c587da2b9a2c5ae36a0488346b49f11470bd812640d6ccda161434221b98cdb65c5d7cc2988492621822a4e301665033e94207f90b323299b2e0fc24
7
- data.tar.gz: a325782b46feeaf314a94f758be89d02b006fabfe824c91b2ac17309841980cab4cb9129318040426d9d6582bff6dd7345bc40f9234b0cd2e89c0d5555948335
6
+ metadata.gz: 894766215e6e1e6d942e3afbc5a1c797dbf5abf7a885a0a63e9fb29985e77f9ff84449d53f147484b0edb041e6bd89094b2824e3144ba0020cbadb8dc9fb9943
7
+ data.tar.gz: 69806e7e4ff2cd9184c63a906ca25d44a69003c52e477fe96fa563bc99590f117b0701e0231cf8543e617cb31f63c0ed615a2d54ff8d757e00eb1e420d637d1d
@@ -1,3 +1,3 @@
1
1
  module IOStreams
2
- VERSION = '0.20.1'
2
+ VERSION = '0.20.2'
3
3
  end
@@ -3,7 +3,12 @@ module IOStreams
3
3
  class Reader
4
4
  # Read from a zip file or stream, decompressing the contents as it is read
5
5
  # The input stream from the first file found in the zip file is passed
6
- # to the supplied block
6
+ # to the supplied block.
7
+ #
8
+ # Parameters:
9
+ # entry_file_name: [String]
10
+ # Name of the file within the Zip file to read.
11
+ # Default: Read the first file found in the zip file.
7
12
  #
8
13
  # Example:
9
14
  # IOStreams::Zip::Reader.open('abc.zip') do |io_stream|
@@ -12,58 +17,65 @@ module IOStreams
12
17
  # puts data
13
18
  # end
14
19
  # end
15
- def self.open(file_name_or_io, _ = nil, &block)
16
- if !defined?(JRuby) && !defined?(::Zip)
17
- # MRI needs Ruby Zip, since it only has native support for GZip
18
- begin
19
- require 'zip'
20
- rescue LoadError => exc
21
- raise(LoadError, "Install gem 'rubyzip' to read and write Zip files: #{exc.message}")
22
- end
23
- end
24
-
20
+ def self.open(file_name_or_io, entry_file_name: nil, &block)
25
21
  # File name supplied
26
- return read_file(file_name_or_io, &block) unless IOStreams.reader_stream?(file_name_or_io)
22
+ return read_file(file_name_or_io, entry_file_name, &block) unless IOStreams.reader_stream?(file_name_or_io)
27
23
 
28
- # ZIP can only work against a file, not a stream, so create temp file.
24
+ # Ruby ZIP gem uses `#seek` so can only work against a file, not a stream, so create temp file.
25
+ # JRuby ZIP requires an InputStream.
29
26
  IOStreams::File::Path.temp_file_name('iostreams_zip') do |temp_file_name|
30
27
  IOStreams.copy(file_name_or_io, temp_file_name, target_options: {streams: []})
31
- read_file(temp_file_name, &block)
28
+ read_file(temp_file_name, entry_file_name, &block)
32
29
  end
33
30
  end
34
31
 
35
32
  if defined?(JRuby)
36
33
  # Java has built-in support for Zip files
37
- def self.read_file(file_name, &block)
34
+ def self.read_file(file_name, entry_file_name)
38
35
  fin = Java::JavaIo::FileInputStream.new(file_name)
39
36
  zin = Java::JavaUtilZip::ZipInputStream.new(fin)
40
- zin.get_next_entry
41
- block.call(zin.to_io)
37
+
38
+ get_entry(zin, entry_file_name) ||
39
+ raise(Java::JavaUtilZip::ZipException.new("File #{entry_file_name} not found within zip file."))
40
+
41
+ yield(zin.to_io)
42
42
  ensure
43
43
  zin.close if zin
44
44
  fin.close if fin
45
45
  end
46
46
 
47
47
  else
48
-
49
48
  # Read from a zip file or stream, decompressing the contents as it is read
50
49
  # The input stream from the first file found in the zip file is passed
51
50
  # to the supplied block
52
- def self.read_file(file_name, &block)
53
- begin
54
- zin = ::Zip::InputStream.new(file_name)
55
- zin.get_next_entry
56
- block.call(zin)
57
- ensure
51
+ def self.read_file(file_name, entry_file_name)
52
+ if !defined?(::Zip)
53
+ # MRI needs Ruby Zip, since it only has native support for GZip
58
54
  begin
59
- zin.close if zin
60
- rescue IOError
61
- # Ignore file already closed errors since Zip::InputStream
62
- # does not have a #closed? method
55
+ require 'zip'
56
+ rescue LoadError => exc
57
+ raise(LoadError, "Install gem 'rubyzip' to read and write Zip files: #{exc.message}")
63
58
  end
64
59
  end
60
+
61
+ ::Zip::InputStream.open(file_name) do |zin|
62
+ get_entry(zin, entry_file_name) ||
63
+ raise(::Zip::EntryNameError, "File #{entry_file_name} not found within zip file.")
64
+ yield(zin)
65
+ end
65
66
  end
67
+ end
66
68
 
69
+ def self.get_entry(zin, entry_file_name)
70
+ if entry_file_name.nil?
71
+ zin.get_next_entry
72
+ return true
73
+ end
74
+
75
+ while entry = zin.get_next_entry
76
+ return true if entry.name == entry_file_name
77
+ end
78
+ false
67
79
  end
68
80
  end
69
81
  end
Binary file
Binary file
@@ -30,6 +30,22 @@ class IOStreamsTest < Minitest::Test
30
30
  bad_data.gsub("\xE9".b, '').gsub("\x07", '')
31
31
  end
32
32
 
33
+ let :multiple_zip_file_name do
34
+ File.join(File.dirname(__FILE__), 'files', 'multiple_files.zip')
35
+ end
36
+
37
+ let :zip_gz_file_name do
38
+ File.join(File.dirname(__FILE__), 'files', 'text.zip.gz')
39
+ end
40
+
41
+ let :contents_test_txt do
42
+ File.read(File.join(File.dirname(__FILE__), 'files', 'text.txt'))
43
+ end
44
+
45
+ let :contents_test_json do
46
+ File.read(File.join(File.dirname(__FILE__), 'files', 'test.json'))
47
+ end
48
+
33
49
  after do
34
50
  temp_file.delete
35
51
  end
@@ -124,5 +140,20 @@ class IOStreamsTest < Minitest::Test
124
140
  end
125
141
  end
126
142
 
143
+ describe '.reader' do
144
+ it 'reads a zip file' do
145
+ result = IOStreams.reader(multiple_zip_file_name, streams: {zip: {entry_file_name: 'test.json'}}) do |io|
146
+ io.read
147
+ end
148
+ assert_equal contents_test_json, result
149
+ end
150
+
151
+ it 'reads a zip file from within a gz file' do
152
+ result = IOStreams.reader(zip_gz_file_name) do |io|
153
+ io.read
154
+ end
155
+ assert_equal contents_test_txt, result
156
+ end
157
+ end
127
158
  end
128
159
  end
@@ -0,0 +1,25 @@
1
+ # The miminum methods that any IOStreams Reader must implement.
2
+ class MinimalFileReader
3
+ def self.open(file_name)
4
+ io = new(file_name)
5
+ yield(io)
6
+ ensure
7
+ io.close if io
8
+ end
9
+
10
+ def initialize(file_name)
11
+ @file = File.open(file_name)
12
+ end
13
+
14
+ def read(size = nil, outbuf = nil)
15
+ @file.read(size, outbuf)
16
+ end
17
+
18
+ def close
19
+ @file.close
20
+ end
21
+
22
+ def closed?
23
+ @file.closed
24
+ end
25
+ end
@@ -1,4 +1,5 @@
1
1
  require_relative 'test_helper'
2
+ require_relative 'minimal_file_reader'
2
3
  require 'zip'
3
4
 
4
5
  class ZipReaderTest < Minitest::Test
@@ -7,20 +8,46 @@ class ZipReaderTest < Minitest::Test
7
8
  File.join(File.dirname(__FILE__), 'files', 'text.zip')
8
9
  end
9
10
 
11
+ let :multiple_zip_file_name do
12
+ File.join(File.dirname(__FILE__), 'files', 'multiple_files.zip')
13
+ end
14
+
15
+ let :contents_test_txt do
16
+ File.read(File.join(File.dirname(__FILE__), 'files', 'text.txt'))
17
+ end
18
+
19
+ let :contents_test_json do
20
+ File.read(File.join(File.dirname(__FILE__), 'files', 'test.json'))
21
+ end
22
+
10
23
  let :decompressed do
11
24
  Zip::File.open(file_name) { |zip_file| zip_file.first.get_input_stream.read }
12
25
  end
13
26
 
14
27
  describe '.open' do
15
- it 'file' do
28
+ it 'reads the first file' do
16
29
  result = IOStreams::Zip::Reader.open(file_name) do |io|
17
30
  io.read
18
31
  end
19
32
  assert_equal decompressed, result
20
33
  end
21
34
 
22
- it 'stream' do
23
- result = File.open(file_name) do |file|
35
+ it 'reads entry within zip file' do
36
+ result = IOStreams::Zip::Reader.open(multiple_zip_file_name, entry_file_name: 'text.txt') do |io|
37
+ io.read
38
+ end
39
+ assert_equal contents_test_txt, result
40
+ end
41
+
42
+ it 'reads another entry within zip file' do
43
+ result = IOStreams::Zip::Reader.open(multiple_zip_file_name, entry_file_name: 'test.json') do |io|
44
+ io.read
45
+ end
46
+ assert_equal contents_test_json, result
47
+ end
48
+
49
+ it 'reads from a stream' do
50
+ result = MinimalFileReader.open(file_name) do |file|
24
51
  IOStreams::Zip::Reader.open(file) do |io|
25
52
  io.read
26
53
  end
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: 0.20.1
4
+ version: 0.20.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Reid Morrison
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-08-24 00:00:00.000000000 Z
11
+ date: 2019-09-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -89,6 +89,7 @@ files:
89
89
  - test/file_reader_test.rb
90
90
  - test/file_writer_test.rb
91
91
  - test/files/embedded_lines_test.csv
92
+ - test/files/multiple_files.zip
92
93
  - test/files/spreadsheet.xlsx
93
94
  - test/files/test.csv
94
95
  - test/files/test.json
@@ -97,6 +98,7 @@ files:
97
98
  - test/files/text.txt.gz
98
99
  - test/files/text.txt.gz.zip
99
100
  - test/files/text.zip
101
+ - test/files/text.zip.gz
100
102
  - test/files/unclosed_quote_test.csv
101
103
  - test/gzip_reader_test.rb
102
104
  - test/gzip_writer_test.rb
@@ -104,6 +106,7 @@ files:
104
106
  - test/io_streams_test.rb
105
107
  - test/line_reader_test.rb
106
108
  - test/line_writer_test.rb
109
+ - test/minimal_file_reader.rb
107
110
  - test/path_test.rb
108
111
  - test/pgp_reader_test.rb
109
112
  - test/pgp_test.rb
@@ -147,6 +150,7 @@ test_files:
147
150
  - test/base_path_test.rb
148
151
  - test/line_reader_test.rb
149
152
  - test/xlsx_reader_test.rb
153
+ - test/minimal_file_reader.rb
150
154
  - test/row_writer_test.rb
151
155
  - test/zip_reader_test.rb
152
156
  - test/bzip2_writer_test.rb
@@ -166,11 +170,13 @@ test_files:
166
170
  - test/files/embedded_lines_test.csv
167
171
  - test/files/test.csv
168
172
  - test/files/test.json
173
+ - test/files/text.zip.gz
169
174
  - test/files/unclosed_quote_test.csv
170
175
  - test/files/text.txt.bz2
171
176
  - test/files/text.txt.gz.zip
172
177
  - test/files/text.txt.gz
173
178
  - test/files/text.txt
179
+ - test/files/multiple_files.zip
174
180
  - test/gzip_reader_test.rb
175
181
  - test/encode_reader_test.rb
176
182
  - test/test_helper.rb