iostreams 1.10.3 → 2.0.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 +20 -2
- data/Rakefile +7 -0
- data/lib/io_streams/builder.rb +10 -10
- data/lib/io_streams/bzip2/writer.rb +1 -1
- data/lib/io_streams/encode/reader.rb +2 -2
- data/lib/io_streams/encode/writer.rb +5 -5
- data/lib/io_streams/gzip/reader.rb +1 -1
- data/lib/io_streams/gzip/writer.rb +1 -1
- data/lib/io_streams/io_streams.rb +47 -21
- data/lib/io_streams/line/reader.rb +2 -2
- data/lib/io_streams/line/writer.rb +1 -1
- data/lib/io_streams/path.rb +2 -2
- data/lib/io_streams/paths/file.rb +25 -11
- data/lib/io_streams/paths/http.rb +80 -7
- data/lib/io_streams/paths/matcher.rb +3 -3
- data/lib/io_streams/paths/s3.rb +22 -3
- data/lib/io_streams/paths/sftp.rb +9 -10
- data/lib/io_streams/pgp/reader.rb +25 -7
- data/lib/io_streams/pgp/writer.rb +95 -29
- data/lib/io_streams/pgp.rb +289 -87
- data/lib/io_streams/reader.rb +4 -4
- data/lib/io_streams/record/reader.rb +3 -4
- 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 +36 -30
- data/lib/io_streams/symmetric_encryption/reader.rb +2 -2
- data/lib/io_streams/symmetric_encryption/writer.rb +4 -4
- data/lib/io_streams/tabular/header.rb +18 -6
- data/lib/io_streams/tabular/parser/array.rb +0 -10
- data/lib/io_streams/tabular/parser/csv.rb +6 -38
- data/lib/io_streams/tabular/parser/fixed.rb +5 -5
- data/lib/io_streams/tabular/parser/psv.rb +0 -12
- data/lib/io_streams/tabular.rb +5 -10
- data/lib/io_streams/utils.rb +6 -8
- data/lib/io_streams/version.rb +1 -1
- data/lib/io_streams/writer.rb +6 -6
- data/lib/io_streams/xlsx/reader.rb +1 -1
- data/lib/io_streams/zip/writer.rb +22 -10
- data/lib/iostreams.rb +0 -1
- metadata +28 -113
- 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/files/utf16_test.csv +0 -0
- 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 -202
- 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 -254
- 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 -574
- 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
data/test/files/utf16_test.csv
DELETED
|
Binary file
|
data/test/gzip_reader_test.rb
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
require_relative "test_helper"
|
|
2
|
-
|
|
3
|
-
class GzipReaderTest < Minitest::Test
|
|
4
|
-
describe IOStreams::Gzip::Reader do
|
|
5
|
-
let :file_name do
|
|
6
|
-
File.join(File.dirname(__FILE__), "files", "text.txt.gz")
|
|
7
|
-
end
|
|
8
|
-
|
|
9
|
-
let :decompressed do
|
|
10
|
-
Zlib::GzipReader.open(file_name, &:read)
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
describe ".open" do
|
|
14
|
-
it "file" do
|
|
15
|
-
result = IOStreams::Gzip::Reader.file(file_name, &:read)
|
|
16
|
-
assert_equal decompressed, result
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
it "stream" do
|
|
20
|
-
result = File.open(file_name) do |file|
|
|
21
|
-
IOStreams::Gzip::Reader.stream(file, &:read)
|
|
22
|
-
end
|
|
23
|
-
assert_equal decompressed, result
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
end
|
data/test/gzip_writer_test.rb
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
require_relative "test_helper"
|
|
2
|
-
|
|
3
|
-
class GzipWriterTest < Minitest::Test
|
|
4
|
-
describe IOStreams::Gzip::Writer do
|
|
5
|
-
let :temp_file do
|
|
6
|
-
Tempfile.new("iostreams")
|
|
7
|
-
end
|
|
8
|
-
|
|
9
|
-
let :file_name do
|
|
10
|
-
temp_file.path
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
let :decompressed do
|
|
14
|
-
File.read(File.join(File.dirname(__FILE__), "files", "text.txt"))
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
after do
|
|
18
|
-
temp_file.delete
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
describe ".file" do
|
|
22
|
-
it "file" do
|
|
23
|
-
result =
|
|
24
|
-
IOStreams::Gzip::Writer.file(file_name) do |io|
|
|
25
|
-
io.write(decompressed)
|
|
26
|
-
53534
|
|
27
|
-
end
|
|
28
|
-
assert_equal 53534, result
|
|
29
|
-
|
|
30
|
-
result = Zlib::GzipReader.open(file_name, &:read)
|
|
31
|
-
temp_file.delete
|
|
32
|
-
assert_equal decompressed, result
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
it "stream" do
|
|
36
|
-
io_string = StringIO.new("".b)
|
|
37
|
-
result =
|
|
38
|
-
IOStreams::Gzip::Writer.stream(io_string) do |io|
|
|
39
|
-
io.write(decompressed)
|
|
40
|
-
53534
|
|
41
|
-
end
|
|
42
|
-
assert_equal 53534, result
|
|
43
|
-
|
|
44
|
-
io = StringIO.new(io_string.string)
|
|
45
|
-
gz = Zlib::GzipReader.new(io)
|
|
46
|
-
data = gz.read
|
|
47
|
-
gz.close
|
|
48
|
-
assert_equal decompressed, data
|
|
49
|
-
end
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
end
|
data/test/io_streams_test.rb
DELETED
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
require_relative "test_helper"
|
|
2
|
-
require "json"
|
|
3
|
-
|
|
4
|
-
module IOStreams
|
|
5
|
-
class PathTest < Minitest::Test
|
|
6
|
-
describe IOStreams do
|
|
7
|
-
let :records do
|
|
8
|
-
[
|
|
9
|
-
{"name" => "Jack Jones", "login" => "jjones"},
|
|
10
|
-
{"name" => "Jill Smith", "login" => "jsmith"}
|
|
11
|
-
]
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
let :expected_json do
|
|
15
|
-
records.collect(&:to_json).join("\n") + "\n"
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
let :json_file_name do
|
|
19
|
-
"/tmp/iostreams_abc.json"
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
describe ".root" do
|
|
23
|
-
it "return default path" do
|
|
24
|
-
path = ::File.expand_path(::File.join(__dir__, "../tmp/default"))
|
|
25
|
-
assert_equal path, IOStreams.root.to_s
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
it "return downloads path" do
|
|
29
|
-
path = ::File.expand_path(::File.join(__dir__, "../tmp/downloads"))
|
|
30
|
-
assert_equal path, IOStreams.root(:downloads).to_s
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
describe ".join" do
|
|
35
|
-
it "returns path" do
|
|
36
|
-
assert_equal IOStreams.root.to_s, IOStreams.join.to_s
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
it "adds path to root" do
|
|
40
|
-
assert_equal ::File.join(IOStreams.root.to_s, "test"), IOStreams.join("test").to_s
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
it "adds paths to root" do
|
|
44
|
-
assert_equal ::File.join(IOStreams.root.to_s, "test", "second", "third"), IOStreams.join("test", "second", "third").to_s
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
it "returns path and filename" do
|
|
48
|
-
path = ::File.join(IOStreams.root.to_s, "file.xls")
|
|
49
|
-
assert_equal path, IOStreams.join("file.xls").to_s
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
it "adds path to root and filename" do
|
|
53
|
-
path = ::File.join(IOStreams.root.to_s, "test", "file.xls")
|
|
54
|
-
assert_equal path, IOStreams.join("test", "file.xls").to_s
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
it "adds paths to root" do
|
|
58
|
-
path = ::File.join(IOStreams.root.to_s, "test", "second", "third", "file.xls")
|
|
59
|
-
assert_equal path, IOStreams.join("test", "second", "third", "file.xls").to_s
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
it "return path as sent in when full path" do
|
|
63
|
-
path = ::File.join(IOStreams.root.to_s, "file.xls")
|
|
64
|
-
assert_equal path, IOStreams.join(path).to_s
|
|
65
|
-
end
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
describe ".path" do
|
|
69
|
-
it "default" do
|
|
70
|
-
path = IOStreams.path("a.xyz")
|
|
71
|
-
assert path.is_a?(IOStreams::Paths::File), path
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
it "s3" do
|
|
75
|
-
skip "TODO"
|
|
76
|
-
IOStreams.path("s3://a.xyz")
|
|
77
|
-
assert_equal :s3, path
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
it "hash writer detects json format from file name" do
|
|
81
|
-
path = IOStreams.path("/tmp/io_streams/abc.json")
|
|
82
|
-
path.writer(:hash) do |io|
|
|
83
|
-
records.each { |hash| io << hash }
|
|
84
|
-
end
|
|
85
|
-
actual = path.read
|
|
86
|
-
path.delete
|
|
87
|
-
assert_equal expected_json, actual
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
it "hash reader detects json format from file name" do
|
|
91
|
-
::File.open(json_file_name, "wb") { |file| file.write(expected_json) }
|
|
92
|
-
rows = []
|
|
93
|
-
path = IOStreams.path(json_file_name)
|
|
94
|
-
path.each(:hash) do |row|
|
|
95
|
-
rows << row
|
|
96
|
-
end
|
|
97
|
-
actual = rows.collect(&:to_json).join("\n") + "\n"
|
|
98
|
-
path.delete
|
|
99
|
-
assert_equal expected_json, actual
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
it "array writer detects json format from file name" do
|
|
103
|
-
path = IOStreams.path("/tmp/io_streams/abc.json")
|
|
104
|
-
path.writer(:array, columns: %w[name login]) do |io|
|
|
105
|
-
io << ["Jack Jones", "jjones"]
|
|
106
|
-
io << ["Jill Smith", "jsmith"]
|
|
107
|
-
end
|
|
108
|
-
actual = path.read
|
|
109
|
-
path.delete
|
|
110
|
-
assert_equal expected_json, actual
|
|
111
|
-
end
|
|
112
|
-
end
|
|
113
|
-
|
|
114
|
-
describe ".temp_file" do
|
|
115
|
-
it "returns value from block" do
|
|
116
|
-
result = IOStreams.temp_file("base", ".ext") { |_path| 257 }
|
|
117
|
-
assert_equal 257, result
|
|
118
|
-
end
|
|
119
|
-
|
|
120
|
-
it "supplies new temp file_name" do
|
|
121
|
-
path1 = nil
|
|
122
|
-
path2 = nil
|
|
123
|
-
IOStreams.temp_file("base", ".ext") { |path| path1 = path }
|
|
124
|
-
IOStreams.temp_file("base", ".ext") { |path| path2 = path }
|
|
125
|
-
refute_equal path1.to_s, path2.to_s
|
|
126
|
-
assert path1.is_a?(IOStreams::Paths::File), path1
|
|
127
|
-
assert path2.is_a?(IOStreams::Paths::File), path2
|
|
128
|
-
end
|
|
129
|
-
end
|
|
130
|
-
end
|
|
131
|
-
end
|
|
132
|
-
end
|
data/test/line_reader_test.rb
DELETED
|
@@ -1,325 +0,0 @@
|
|
|
1
|
-
require_relative "test_helper"
|
|
2
|
-
|
|
3
|
-
class LineReaderTest < Minitest::Test
|
|
4
|
-
describe IOStreams::Line::Reader do
|
|
5
|
-
let :file_name do
|
|
6
|
-
File.join(File.dirname(__FILE__), "files", "text.txt")
|
|
7
|
-
end
|
|
8
|
-
|
|
9
|
-
let :csv_file do
|
|
10
|
-
File.join(File.dirname(__FILE__), "files", "embedded_lines_test.csv")
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
let :unclosed_quote_file do
|
|
14
|
-
File.join(File.dirname(__FILE__), "files", "unclosed_quote_test.csv")
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
let :unclosed_quote_file2 do
|
|
18
|
-
File.join(File.dirname(__FILE__), "files", "unclosed_quote_test2.csv")
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
let :unclosed_quote_large_file do
|
|
22
|
-
File.join(File.dirname(__FILE__), "files", "unclosed_quote_large_test.csv")
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
let :data do
|
|
26
|
-
data = []
|
|
27
|
-
File.open(file_name, "rt") do |file|
|
|
28
|
-
data << file.readline.strip until file.eof?
|
|
29
|
-
end
|
|
30
|
-
data
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
# Test file has embedded new lines in row 2, 3 and 4
|
|
34
|
-
#
|
|
35
|
-
# name, description, zip
|
|
36
|
-
# "\nJack","Firstname is Jack","234567"
|
|
37
|
-
# "John","Firstname\n is John","234568"
|
|
38
|
-
# "Zack","Firstname is Zack","234568\n"
|
|
39
|
-
#
|
|
40
|
-
describe "embedded_within_quotes" do
|
|
41
|
-
describe "csv file" do
|
|
42
|
-
it "fails to keep embedded lines if flag is not set" do
|
|
43
|
-
lines = []
|
|
44
|
-
IOStreams::Line::Reader.file(csv_file) do |io|
|
|
45
|
-
io.each do |line|
|
|
46
|
-
lines << line
|
|
47
|
-
end
|
|
48
|
-
end
|
|
49
|
-
assert_equal 7, lines.count
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
it "keeps embedded lines if flag is set" do
|
|
53
|
-
lines = []
|
|
54
|
-
IOStreams::Line::Reader.file(csv_file, embedded_within: '"') do |io|
|
|
55
|
-
io.each do |line|
|
|
56
|
-
lines << line
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
assert_equal 4, lines.count
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
it "raises error for unbalanced quotes" do
|
|
63
|
-
exc = assert_raises(IOStreams::Errors::MalformedDataError) do
|
|
64
|
-
IOStreams::Line::Reader.file(unclosed_quote_file, embedded_within: '"') do |io|
|
|
65
|
-
io.each { |line| }
|
|
66
|
-
end
|
|
67
|
-
end
|
|
68
|
-
assert_includes exc.message, "Unbalanced delimited field, delimiter:"
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
it "raises error for unclosed quote" do
|
|
72
|
-
exc = assert_raises(IOStreams::Errors::MalformedDataError) do
|
|
73
|
-
IOStreams::Line::Reader.file(unclosed_quote_file2, embedded_within: '"') do |io|
|
|
74
|
-
io.each { |line| }
|
|
75
|
-
end
|
|
76
|
-
end
|
|
77
|
-
assert_includes exc.message, "Unbalanced delimited field, delimiter:"
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
it "raises error for unclosed quote before eof" do
|
|
81
|
-
exc = assert_raises(IOStreams::Errors::MalformedDataError) do
|
|
82
|
-
IOStreams::Line::Reader.file(unclosed_quote_large_file, embedded_within: '"', buffer_size: 20) do |io|
|
|
83
|
-
io.each { |line| }
|
|
84
|
-
end
|
|
85
|
-
end
|
|
86
|
-
assert_includes exc.message, "Unbalanced delimited field, delimiter:"
|
|
87
|
-
end
|
|
88
|
-
end
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
describe "#each" do
|
|
92
|
-
it "each_line file" do
|
|
93
|
-
lines = []
|
|
94
|
-
count = IOStreams::Line::Reader.file(file_name) do |io|
|
|
95
|
-
io.each { |line| lines << line }
|
|
96
|
-
end
|
|
97
|
-
assert_equal data, lines
|
|
98
|
-
assert_equal data.size, count
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
it "each_line stream" do
|
|
102
|
-
lines = []
|
|
103
|
-
count = File.open(file_name) do |file|
|
|
104
|
-
IOStreams::Line::Reader.stream(file) do |io|
|
|
105
|
-
io.each { |line| lines << line }
|
|
106
|
-
end
|
|
107
|
-
end
|
|
108
|
-
assert_equal data, lines
|
|
109
|
-
assert_equal data.size, count
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
["\r\n", "\n", "\r"].each do |delimiter|
|
|
113
|
-
it "autodetect delimiter: #{delimiter.inspect}" do
|
|
114
|
-
lines = []
|
|
115
|
-
stream = StringIO.new(data.join(delimiter))
|
|
116
|
-
count = IOStreams::Line::Reader.stream(stream, buffer_size: 15) do |io|
|
|
117
|
-
io.each { |line| lines << line }
|
|
118
|
-
end
|
|
119
|
-
assert_equal data, lines
|
|
120
|
-
assert_equal data.size, count
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
it "single read autodetect delimiter: #{delimiter.inspect}" do
|
|
124
|
-
lines = []
|
|
125
|
-
stream = StringIO.new(data.join(delimiter))
|
|
126
|
-
count = IOStreams::Line::Reader.stream(stream) do |io|
|
|
127
|
-
io.each { |line| lines << line }
|
|
128
|
-
end
|
|
129
|
-
assert_equal data, lines
|
|
130
|
-
assert_equal data.size, count
|
|
131
|
-
end
|
|
132
|
-
end
|
|
133
|
-
|
|
134
|
-
["@", "BLAH"].each do |delimiter|
|
|
135
|
-
it "reads delimited #{delimiter.inspect}" do
|
|
136
|
-
lines = []
|
|
137
|
-
stream = StringIO.new(data.join(delimiter))
|
|
138
|
-
count = IOStreams::Line::Reader.stream(stream, buffer_size: 15, delimiter: delimiter) do |io|
|
|
139
|
-
io.each { |line| lines << line }
|
|
140
|
-
end
|
|
141
|
-
assert_equal data, lines
|
|
142
|
-
assert_equal data.size, count
|
|
143
|
-
end
|
|
144
|
-
end
|
|
145
|
-
|
|
146
|
-
it "reads binary delimited" do
|
|
147
|
-
delimiter = "\x01"
|
|
148
|
-
lines = []
|
|
149
|
-
stream = StringIO.new(data.join(delimiter).encode("ASCII-8BIT"))
|
|
150
|
-
count = IOStreams::Line::Reader.stream(stream, buffer_size: 15, delimiter: delimiter) do |io|
|
|
151
|
-
io.each { |line| lines << line }
|
|
152
|
-
end
|
|
153
|
-
assert_equal data, lines
|
|
154
|
-
assert_equal data.size, count
|
|
155
|
-
end
|
|
156
|
-
|
|
157
|
-
describe "#readline" do
|
|
158
|
-
let(:short_line) { "0123456789" }
|
|
159
|
-
let(:longer_line) { "ABCDEFGHIJKLMNOPQRSTUVWXYZ" }
|
|
160
|
-
let(:delimiter) { "\r\n" }
|
|
161
|
-
|
|
162
|
-
it "reads delimiter in first block, no delimiter at end" do
|
|
163
|
-
data = [short_line, longer_line].join(delimiter)
|
|
164
|
-
buffer_size = short_line.length + delimiter.size + (longer_line.size / 2)
|
|
165
|
-
|
|
166
|
-
stream = StringIO.new(data)
|
|
167
|
-
IOStreams::Line::Reader.stream(stream, buffer_size: buffer_size) do |io|
|
|
168
|
-
refute io.eof?
|
|
169
|
-
assert_equal delimiter, io.delimiter, -> { io.delimiter.ai }
|
|
170
|
-
|
|
171
|
-
assert_equal short_line, io.readline
|
|
172
|
-
assert_equal longer_line, io.readline
|
|
173
|
-
|
|
174
|
-
assert io.eof?
|
|
175
|
-
assert_nil io.readline
|
|
176
|
-
end
|
|
177
|
-
end
|
|
178
|
-
|
|
179
|
-
it "reads delimiter in second block, no delimiter at end" do
|
|
180
|
-
data = [longer_line, short_line, short_line].join(delimiter)
|
|
181
|
-
buffer_size = (longer_line.length + delimiter.size + 5) / 2
|
|
182
|
-
|
|
183
|
-
stream = StringIO.new(data)
|
|
184
|
-
IOStreams::Line::Reader.stream(stream, buffer_size: buffer_size) do |io|
|
|
185
|
-
refute io.eof?
|
|
186
|
-
assert_equal delimiter, io.delimiter, -> { io.delimiter.ai }
|
|
187
|
-
assert_equal longer_line, io.readline
|
|
188
|
-
assert_equal short_line, io.readline
|
|
189
|
-
assert_equal short_line, io.readline
|
|
190
|
-
assert io.eof?
|
|
191
|
-
assert_nil io.readline
|
|
192
|
-
end
|
|
193
|
-
end
|
|
194
|
-
|
|
195
|
-
it "reads delimiter split across first and second blocks" do
|
|
196
|
-
data = [longer_line, short_line, short_line].join(delimiter)
|
|
197
|
-
buffer_size = longer_line.length + 1
|
|
198
|
-
|
|
199
|
-
stream = StringIO.new(data)
|
|
200
|
-
IOStreams::Line::Reader.stream(stream, buffer_size: buffer_size) do |io|
|
|
201
|
-
refute io.eof?
|
|
202
|
-
assert_equal delimiter, io.delimiter, -> { io.delimiter.ai }
|
|
203
|
-
assert_equal longer_line, io.readline
|
|
204
|
-
assert_equal short_line, io.readline
|
|
205
|
-
assert_equal short_line, io.readline
|
|
206
|
-
assert io.eof?
|
|
207
|
-
assert_nil io.readline
|
|
208
|
-
end
|
|
209
|
-
end
|
|
210
|
-
|
|
211
|
-
it "reads file with no matching delimiter" do
|
|
212
|
-
delimiter = "@"
|
|
213
|
-
data = [longer_line, short_line, longer_line].join(delimiter) + delimiter
|
|
214
|
-
buffer_size = longer_line.length + 1
|
|
215
|
-
|
|
216
|
-
stream = StringIO.new(data)
|
|
217
|
-
IOStreams::Line::Reader.stream(stream, buffer_size: buffer_size) do |io|
|
|
218
|
-
refute io.eof?
|
|
219
|
-
assert_equal "\n", io.delimiter, -> { io.delimiter.ai }
|
|
220
|
-
assert_equal data, io.readline
|
|
221
|
-
assert io.eof?
|
|
222
|
-
assert_nil io.readline
|
|
223
|
-
end
|
|
224
|
-
end
|
|
225
|
-
|
|
226
|
-
it "reads small file with no matching delimiter" do
|
|
227
|
-
data = short_line
|
|
228
|
-
buffer_size = short_line.length + 100
|
|
229
|
-
|
|
230
|
-
stream = StringIO.new(data)
|
|
231
|
-
IOStreams::Line::Reader.stream(stream, buffer_size: buffer_size) do |io|
|
|
232
|
-
refute io.eof?
|
|
233
|
-
assert_equal "\n", io.delimiter, -> { io.delimiter.ai }
|
|
234
|
-
assert_equal short_line, io.readline
|
|
235
|
-
assert io.eof?
|
|
236
|
-
assert_nil io.readline
|
|
237
|
-
end
|
|
238
|
-
end
|
|
239
|
-
|
|
240
|
-
it "reads last line with the delimiter as the last character" do
|
|
241
|
-
delimiter = "@"
|
|
242
|
-
data = [longer_line, short_line, longer_line].join(delimiter) + delimiter
|
|
243
|
-
buffer_size = longer_line.length + 1
|
|
244
|
-
|
|
245
|
-
stream = StringIO.new(data)
|
|
246
|
-
IOStreams::Line::Reader.stream(stream, buffer_size: buffer_size, delimiter: delimiter) do |io|
|
|
247
|
-
refute io.eof?
|
|
248
|
-
assert_equal delimiter, io.delimiter, -> { io.delimiter.ai }
|
|
249
|
-
assert_equal longer_line, io.readline
|
|
250
|
-
assert_equal short_line, io.readline
|
|
251
|
-
assert_equal longer_line, io.readline
|
|
252
|
-
assert_nil io.readline
|
|
253
|
-
assert io.eof?
|
|
254
|
-
end
|
|
255
|
-
end
|
|
256
|
-
|
|
257
|
-
it "reads last line with the multi-byte delimiter as the last bytes" do
|
|
258
|
-
data = [longer_line, short_line, longer_line].join(delimiter) + delimiter
|
|
259
|
-
buffer_size = longer_line.length + 1
|
|
260
|
-
|
|
261
|
-
stream = StringIO.new(data)
|
|
262
|
-
IOStreams::Line::Reader.stream(stream, buffer_size: buffer_size) do |io|
|
|
263
|
-
refute io.eof?
|
|
264
|
-
assert_equal delimiter, io.delimiter, -> { io.delimiter.ai }
|
|
265
|
-
assert_equal longer_line, io.readline
|
|
266
|
-
assert_equal short_line, io.readline
|
|
267
|
-
assert_equal longer_line, io.readline
|
|
268
|
-
assert_nil io.readline
|
|
269
|
-
assert io.eof?
|
|
270
|
-
end
|
|
271
|
-
end
|
|
272
|
-
|
|
273
|
-
describe "read 1 char at a time" do
|
|
274
|
-
let(:buffer_size) { 1 }
|
|
275
|
-
|
|
276
|
-
it "delimiter at the end" do
|
|
277
|
-
data = [longer_line, short_line, longer_line].join(delimiter) + delimiter
|
|
278
|
-
|
|
279
|
-
stream = StringIO.new(data)
|
|
280
|
-
IOStreams::Line::Reader.stream(stream, buffer_size: buffer_size) do |io|
|
|
281
|
-
refute io.eof?
|
|
282
|
-
assert_equal delimiter, io.delimiter, -> { io.delimiter.ai }
|
|
283
|
-
assert_equal longer_line, io.readline
|
|
284
|
-
assert_equal short_line, io.readline
|
|
285
|
-
assert_equal longer_line, io.readline
|
|
286
|
-
assert_nil io.readline
|
|
287
|
-
assert io.eof?
|
|
288
|
-
end
|
|
289
|
-
end
|
|
290
|
-
|
|
291
|
-
it "no delimiter at the end" do
|
|
292
|
-
data = [longer_line, short_line, longer_line].join(delimiter)
|
|
293
|
-
|
|
294
|
-
stream = StringIO.new(data)
|
|
295
|
-
IOStreams::Line::Reader.stream(stream, buffer_size: buffer_size) do |io|
|
|
296
|
-
refute io.eof?
|
|
297
|
-
assert_equal delimiter, io.delimiter, -> { io.delimiter.ai }
|
|
298
|
-
assert_equal longer_line, io.readline
|
|
299
|
-
assert_equal short_line, io.readline
|
|
300
|
-
assert_equal longer_line, io.readline
|
|
301
|
-
assert_nil io.readline
|
|
302
|
-
assert io.eof?
|
|
303
|
-
end
|
|
304
|
-
end
|
|
305
|
-
end
|
|
306
|
-
|
|
307
|
-
it "reads empty file" do
|
|
308
|
-
stream = StringIO.new
|
|
309
|
-
IOStreams::Line::Reader.stream(stream) do |io|
|
|
310
|
-
assert io.eof?
|
|
311
|
-
end
|
|
312
|
-
end
|
|
313
|
-
|
|
314
|
-
it "prevents denial of service" do
|
|
315
|
-
data = "a" * IOStreams::Line::Reader::MAX_BLOCKS_MULTIPLIER + "a"
|
|
316
|
-
stream = StringIO.new(data)
|
|
317
|
-
assert_raises IOStreams::Errors::DelimiterNotFound do
|
|
318
|
-
IOStreams::Line::Reader.stream(stream, buffer_size: 1) do |io|
|
|
319
|
-
end
|
|
320
|
-
end
|
|
321
|
-
end
|
|
322
|
-
end
|
|
323
|
-
end
|
|
324
|
-
end
|
|
325
|
-
end
|
data/test/line_writer_test.rb
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
require_relative "test_helper"
|
|
2
|
-
|
|
3
|
-
class DelimitedWriterTest < Minitest::Test
|
|
4
|
-
describe IOStreams::Line::Writer do
|
|
5
|
-
let :file_name do
|
|
6
|
-
File.join(File.dirname(__FILE__), "files", "text.txt")
|
|
7
|
-
end
|
|
8
|
-
|
|
9
|
-
let :raw do
|
|
10
|
-
File.read(file_name)
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
let :lines do
|
|
14
|
-
raw.lines.map(&:strip)
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
describe "#<<" do
|
|
18
|
-
it "file" do
|
|
19
|
-
temp_file = Tempfile.new("rocket_job")
|
|
20
|
-
file_name = temp_file.to_path
|
|
21
|
-
result =
|
|
22
|
-
IOStreams::Line::Writer.file(file_name) do |io|
|
|
23
|
-
lines.each { |line| io << line }
|
|
24
|
-
53534
|
|
25
|
-
end
|
|
26
|
-
assert_equal 53534, result
|
|
27
|
-
|
|
28
|
-
result = File.read(file_name)
|
|
29
|
-
assert_equal raw, result
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
it "stream" do
|
|
33
|
-
io_string = StringIO.new
|
|
34
|
-
result =
|
|
35
|
-
IOStreams::Line::Writer.stream(io_string) do |io|
|
|
36
|
-
lines.each { |line| io << line }
|
|
37
|
-
53534
|
|
38
|
-
end
|
|
39
|
-
assert_equal 53534, result
|
|
40
|
-
assert_equal raw, io_string.string
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
describe ".write" do
|
|
45
|
-
it "returns byte count" do
|
|
46
|
-
io_string = StringIO.new
|
|
47
|
-
count = 0
|
|
48
|
-
result =
|
|
49
|
-
IOStreams::Line::Writer.stream(io_string) do |io|
|
|
50
|
-
lines.each { |line| count += io.write(line) }
|
|
51
|
-
53534
|
|
52
|
-
end
|
|
53
|
-
assert_equal 53534, result
|
|
54
|
-
assert_equal raw, io_string.string
|
|
55
|
-
assert_equal raw.size, count
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
end
|
data/test/minimal_file_reader.rb
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
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
|
|
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
|
data/test/path_test.rb
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
require_relative "test_helper"
|
|
2
|
-
|
|
3
|
-
module IOStreams
|
|
4
|
-
class PathTest < Minitest::Test
|
|
5
|
-
describe IOStreams::Path do
|
|
6
|
-
describe ".join" do
|
|
7
|
-
let(:path) { IOStreams::Path.new("some_path") }
|
|
8
|
-
|
|
9
|
-
it "returns self when no elements" do
|
|
10
|
-
assert_equal path.object_id, path.join.object_id
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
it "adds element to path" do
|
|
14
|
-
assert_equal ::File.join("some_path", "test"), path.join("test").to_s
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
it "adds paths to root" do
|
|
18
|
-
assert_equal ::File.join("some_path", "test", "second", "third"), path.join("test", "second", "third").to_s
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
it "returns path and filename" do
|
|
22
|
-
assert_equal ::File.join("some_path", "file.xls"), path.join("file.xls").to_s
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
it "adds elements to path" do
|
|
26
|
-
assert_equal ::File.join("some_path", "test", "second", "third", "file.xls"), path.join("test", "second", "third", "file.xls").to_s
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
it "return path as sent in when full path" do
|
|
30
|
-
assert_equal ::File.join("some_path", "test", "second", "third", "file.xls"), path.join("some_path", "test", "second", "third", "file.xls").to_s
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
describe "#absolute?" do
|
|
35
|
-
it "true on absolute" do
|
|
36
|
-
assert_equal true, IOStreams::Path.new("/a/b/c/d").absolute?
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
it "false when not absolute" do
|
|
40
|
-
assert_equal false, IOStreams::Path.new("a/b/c/d").absolute?
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
describe "#relatve?" do
|
|
45
|
-
it "true on relative" do
|
|
46
|
-
assert_equal true, IOStreams::Path.new("a/b/c/d").relative?
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
it "false on absolute" do
|
|
50
|
-
assert_equal false, IOStreams::Path.new("/a/b/c/d").relative?
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
end
|