compact_csv 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 3dbb0962e7cbb7f04777000bc6e2534701939eb0
4
+ data.tar.gz: 420a6b3f16eccce240928c540b5976894608065e
5
+ SHA512:
6
+ metadata.gz: a07ff8599a91e282ce914db8eab092fd9ba7756e473e7a8e2010bd3ef33024ecb279aea64c545a54803f917eaa59ea534e2c39606db392f7c6af4ab7776ab8da
7
+ data.tar.gz: 9ef10c138a4e98d5c5090bcbbd3dea25d34a91cadc3aa431b96830e769f14a5197423c7a865953ca3a923570abf7afe811ded03e076d2c28448c6920dd6c7eba
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ .ruby-version
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.0
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in compact_csv.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 NAKANO Ryusuke
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,46 @@
1
+ # CompactCSV
2
+
3
+ [![Build Status](https://travis-ci.org/rnakano/compact_csv.svg?branch=master)](https://travis-ci.org/rnakano/compact_csv)
4
+ [![Coverage Status](https://coveralls.io/repos/rnakano/compact_csv/badge.svg?branch=master&service=github)](https://coveralls.io/github/rnakano/compact_csv?branch=master)
5
+ [![Dependency Status](https://gemnasium.com/rnakano/compact_csv.svg)](https://gemnasium.com/rnakano/compact_csv)
6
+
7
+ CompactCSV is memory efficient csv module for ruby. Reading operations are compatible with default CSV module.
8
+
9
+ However, operations which change fields/values structure of row are not available in CompactCSV. If you want to do this, please use default CSV module.
10
+
11
+ ## Installation
12
+
13
+ Add this line to your application's Gemfile:
14
+
15
+ gem 'compact_csv'
16
+
17
+ And then execute:
18
+
19
+ $ bundle
20
+
21
+ Or install it yourself as:
22
+
23
+ $ gem install compact_csv
24
+
25
+ ## Usage
26
+
27
+ ```ruby
28
+ csv = CompactCSV.read('sample.csv', headers: true)
29
+ csv.each do |row|
30
+ p row # => #<CompactCSV::Row "ID":"1" "VALUE":"A">
31
+ row['VALUE'] = 'AAA'
32
+ p row # => #<CompactCSV::Row "ID":"1" "VALUE":"AAA">
33
+ end
34
+ ```
35
+
36
+ ## Links
37
+
38
+ * ruby default CSV module: https://github.com/ruby/ruby/blob/trunk/lib/csv.rb
39
+
40
+ ## Contributing
41
+
42
+ 1. Fork it ( http://github.com/rnakano/compact_csv/fork )
43
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
44
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
45
+ 4. Push to the branch (`git push origin my-new-feature`)
46
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'compact_csv/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "compact_csv"
8
+ spec.version = VERSION
9
+ spec.authors = ["NAKANO Ryusuke"]
10
+ spec.email = ["rsk.nakano@gmail.com"]
11
+ spec.summary = %q{Memory efficient CSV}
12
+ spec.description = %q{Memory efficient CSV}
13
+ spec.homepage = "https://github.com/rnakano/compact_csv"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.5"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "rspec"
24
+ spec.add_development_dependency "coveralls"
25
+ end
@@ -0,0 +1 @@
1
+ VERSION = "0.0.1"
@@ -0,0 +1,146 @@
1
+ require 'csv'
2
+
3
+ class CompactCSV < CSV
4
+ require_relative 'compact_csv/version'
5
+
6
+ class CompatibilityError < StandardError
7
+ end
8
+
9
+ class Table < CSV::Table
10
+ end
11
+
12
+ class Row < CSV::Row
13
+ def initialize(headers, fields, header_row = false)
14
+ headers.freeze
15
+ @headers = headers
16
+ @row_values = fields
17
+ end
18
+
19
+ def headers
20
+ @headers
21
+ end
22
+
23
+ def row
24
+ if @headers.size >= @row_values.size
25
+ @headers.zip(@row_values).to_a
26
+ else
27
+ @row_values.zip(@headers).map { |pair| pair.reverse! }
28
+ end
29
+ end
30
+
31
+ def header_row?
32
+ false
33
+ end
34
+
35
+ def each(&block)
36
+ row.each(&block)
37
+ self
38
+ end
39
+
40
+ def fields(*headers_and_or_indices)
41
+ if headers_and_or_indices.empty?
42
+ size_diff = @headers.size - @row_values.size
43
+ if size_diff <= 0
44
+ @row_values
45
+ elsif size_diff > 0
46
+ @row_values + Array.new(size_diff, nil)
47
+ end
48
+ else
49
+ headers_and_or_indices.map do |index|
50
+ field(index)
51
+ end
52
+ end
53
+ end
54
+
55
+ def size
56
+ [ @row_values.size, @headers.size ].max
57
+ end
58
+ alias_method :length, :size
59
+
60
+ def empty?
61
+ @row_values.empty?
62
+ end
63
+
64
+ def fetch(header, *varargs)
65
+ raise ArgumentError, "Too many arguments" if varargs.length > 1
66
+ pair = row.assoc(header)
67
+ if pair
68
+ pair.last
69
+ else
70
+ if block_given?
71
+ yield header
72
+ elsif varargs.empty?
73
+ raise KeyError, "key not found: #{header}"
74
+ else
75
+ varargs.first
76
+ end
77
+ end
78
+ end
79
+
80
+ def has_key?(header)
81
+ !!row.assoc(header)
82
+ end
83
+
84
+ def [](index)
85
+ if index.is_a?(Integer)
86
+ @row_values[index]
87
+ else
88
+ i = headers.find_index(index)
89
+ i ? @row_values[i] : nil
90
+ end
91
+ end
92
+ alias_method :field, :[]
93
+
94
+ def []=(index, value)
95
+ if index.is_a?(Integer)
96
+ @row_values[index] = value
97
+ else
98
+ i = headers.find_index(index)
99
+ @row_values[i] = value if i
100
+ end
101
+ end
102
+
103
+ def to_hash
104
+ hash = {}
105
+ @row_values.zip(headers) do |value, row|
106
+ hash[row] = value
107
+ end
108
+ hash
109
+ end
110
+
111
+ def ==(other)
112
+ return row == other.row if other.is_a? CompactCSV::Row
113
+ row == other
114
+ end
115
+
116
+ # not compatible methods
117
+ def <<(arg)
118
+ raise CompatibilityError.new("CompactCSV does not allow to append fields into row. Please use CSV module.")
119
+ end
120
+
121
+ def push(*args)
122
+ raise CompatibilityError.new("CompactCSV does not allow to append fields into row. Please use CSV module.")
123
+ end
124
+
125
+ def delete(header_or_index, minimum_index = 0)
126
+ raise CompatibilityError.new("CompactCSV does not allow to delete fields from row. Please use CSV module.")
127
+ end
128
+
129
+ def delete_if(&block)
130
+ raise CompatibilityError.new("CompactCSV does not allow to delete fields from row. Please use CSV module.")
131
+ end
132
+ end
133
+
134
+ def read
135
+ rows = to_a
136
+ if @use_headers
137
+ CompactCSV::Table.new(rows)
138
+ else
139
+ rows
140
+ end
141
+ end
142
+ end
143
+
144
+ def CompactCSV(*args, &block)
145
+ CompactCSV.instance(*args, &block)
146
+ end
@@ -0,0 +1,156 @@
1
+ require 'spec_helper'
2
+
3
+ describe CompactCSV do
4
+ it 'should have a version number' do
5
+ expect(CompactCSV::VERSION).not_to be nil
6
+ end
7
+
8
+ describe '.read' do
9
+ let(:csv_path) { './spec/data/sample.csv' }
10
+
11
+ it 'loads Array instance from csv file' do
12
+ csv = CompactCSV.read(csv_path)
13
+ expect(csv).to be_instance_of(Array)
14
+ end
15
+
16
+ it 'loads CompactCSV::Table instance from csv file' do
17
+ csv = CompactCSV.read(csv_path, headers: true)
18
+ expect(csv).to be_instance_of(CompactCSV::Table)
19
+ expect(csv).to be_kind_of(CSV::Table)
20
+ end
21
+ end
22
+ end
23
+
24
+ describe CompactCSV::Table do
25
+ describe '#each' do
26
+ let(:csv) { CompactCSV.read('./spec/data/sample.csv', headers: true) }
27
+
28
+ it 'returns rows iterator' do
29
+ csv.each do |row|
30
+ expect(row).to be_instance_of(CompactCSV::Row)
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ describe CompactCSV::Row do
37
+ let(:csv) { CompactCSV.read('./spec/data/sample.csv', headers: true) }
38
+ let(:row) { csv.each.first }
39
+
40
+ describe '#each' do
41
+ it 'returns fields iterator' do
42
+ row.each do |field|
43
+ expect(field).to be_instance_of(Array)
44
+ end
45
+ end
46
+ end
47
+
48
+ describe '#field' do
49
+ it 'reads field value' do
50
+ expect(row['ID']).to eq '1'
51
+ expect(row[0]).to eq '1'
52
+ expect(row['VALUE']).to eq 'A'
53
+ expect(row[1]).to eq 'A'
54
+ end
55
+ end
56
+
57
+ describe '#fields' do
58
+ it 'returns fileds of array' do
59
+ expect(row.fields).to eq ['1', 'A']
60
+ end
61
+
62
+ it 'returns specific fields of array' do
63
+ expect(row.fields('VALUE')).to eq ['A']
64
+ end
65
+ end
66
+
67
+ describe '#size' do
68
+ it 'returns size of fields' do
69
+ expect(row.size).to be 2
70
+ end
71
+ end
72
+
73
+ describe '#to_hash' do
74
+ it 'returns hash form' do
75
+ expect(row.to_hash).to eq({ 'ID' => '1', 'VALUE' => 'A' })
76
+ end
77
+ end
78
+
79
+ describe '#empty?' do
80
+ it 'returns true if values empty' do
81
+ expect(CompactCSV::Row.new([], []).empty?).to be true
82
+ end
83
+
84
+ it 'returns flase if values exist' do
85
+ expect(row.empty?).to be false
86
+ end
87
+ end
88
+
89
+ describe '#fetch' do
90
+ it 'returns value if field exists' do
91
+ expect(row.fetch('VALUE')).to eq 'A'
92
+ end
93
+
94
+ it 'throw KeyError if field does not exist' do
95
+ expect { row.fetch('value') }.to raise_error(KeyError)
96
+ end
97
+
98
+ it 'returns varags if field does not exist' do
99
+ expect(row.fetch('value', 1)).to be 1
100
+ end
101
+ end
102
+
103
+ describe '#has_key?' do
104
+ it 'returns true if field exists' do
105
+ expect(row.has_key?('ID')).to be true
106
+ end
107
+
108
+ it 'returns false if field does not exist' do
109
+ expect(row.has_key?('id')).to be false
110
+ end
111
+ end
112
+
113
+ describe '#[]=' do
114
+ it 'change field value' do
115
+ modify_row = row.dup
116
+ modify_row['VALUE'] = 'AAA'
117
+ expect(modify_row.fields).to eq ['1', 'AAA']
118
+ end
119
+ end
120
+
121
+ describe '#==' do
122
+ it 'returns true with same object' do
123
+ expect(row == row).to be true
124
+ end
125
+
126
+ it 'returns false with other object' do
127
+ dirty_row = row.dup
128
+ dirty_row['VALUE'] = 'B'
129
+ expect(row == dirty_row).to be true
130
+ end
131
+ end
132
+
133
+ describe '#<<' do
134
+ it 'raise CompatibilityError' do
135
+ expect { row << [1, 2] }.to raise_error(CompactCSV::CompatibilityError)
136
+ end
137
+ end
138
+
139
+ describe '#push' do
140
+ it 'raise CompatibilityError' do
141
+ expect { row.push(1) }.to raise_error(CompactCSV::CompatibilityError)
142
+ end
143
+ end
144
+
145
+ describe '#delete' do
146
+ it 'raise CompatibilityError' do
147
+ expect { row.delete(1) }.to raise_error(CompactCSV::CompatibilityError)
148
+ end
149
+ end
150
+
151
+ describe '#delete_if' do
152
+ it 'raise CompatibilityError' do
153
+ expect { row.delete_if(&:nil?) }.to raise_error(CompactCSV::CompatibilityError)
154
+ end
155
+ end
156
+ end
@@ -0,0 +1,5 @@
1
+ ID,VALUE
2
+ 1,"A"
3
+ 2,"B"
4
+ 3,"C"
5
+ 4,"B"
@@ -0,0 +1,2 @@
1
+ This directory was copied and modified from https://github.com/ruby/ruby/tree/ruby_2_2/test/csv
2
+
@@ -0,0 +1,7 @@
1
+ require "test/unit"
2
+
3
+ require_relative "../spec_helper"
4
+ require_relative "with_different_ofs.rb"
5
+
6
+ class TestCompactCSV < Test::Unit::TestCase
7
+ end
@@ -0,0 +1,362 @@
1
+ #!/usr/bin/env ruby -w
2
+ # encoding: UTF-8
3
+
4
+ # tc_interface.rb
5
+ #
6
+ # Created by James Edward Gray II on 2005-10-31.
7
+ # Copyright 2005 James Edward Gray II. You can redistribute or modify this code
8
+ # under the terms of Ruby's license.
9
+
10
+ require_relative "base"
11
+ require "tempfile"
12
+
13
+ class TestCompactCSV::Interface < TestCompactCSV
14
+ extend DifferentOFS
15
+
16
+ def setup
17
+ super
18
+ @tempfile = Tempfile.new(%w"temp .csv")
19
+ @tempfile.close
20
+ @path = @tempfile.path
21
+
22
+ File.open(@path, "wb") do |file|
23
+ file << "1\t2\t3\r\n"
24
+ file << "4\t5\r\n"
25
+ end
26
+
27
+ @expected = [%w{1 2 3}, %w{4 5}]
28
+ end
29
+
30
+ def teardown
31
+ @tempfile.close(true)
32
+ super
33
+ end
34
+
35
+ ### Test Read Interface ###
36
+
37
+ def test_foreach
38
+ CompactCSV.foreach(@path, col_sep: "\t", row_sep: "\r\n") do |row|
39
+ assert_equal(@expected.shift, row)
40
+ end
41
+ end
42
+
43
+ def test_foreach_enum
44
+ CompactCSV.foreach(@path, col_sep: "\t", row_sep: "\r\n").zip(@expected) do |row, exp|
45
+ assert_equal(exp, row)
46
+ end
47
+ end
48
+
49
+ def test_open_and_close
50
+ csv = CompactCSV.open(@path, "r+", col_sep: "\t", row_sep: "\r\n")
51
+ assert_not_nil(csv)
52
+ assert_instance_of(CompactCSV, csv)
53
+ assert_not_predicate(csv, :closed?)
54
+ csv.close
55
+ assert_predicate(csv, :closed?)
56
+
57
+ ret = CompactCSV.open(@path) do |new_csv|
58
+ csv = new_csv
59
+ assert_instance_of(CompactCSV, new_csv)
60
+ "Return value."
61
+ end
62
+ assert_predicate(csv, :closed?)
63
+ assert_equal("Return value.", ret)
64
+ end
65
+
66
+ def test_parse
67
+ data = File.binread(@path)
68
+ assert_equal( @expected,
69
+ CompactCSV.parse(data, col_sep: "\t", row_sep: "\r\n") )
70
+
71
+ CompactCSV.parse(data, col_sep: "\t", row_sep: "\r\n") do |row|
72
+ assert_equal(@expected.shift, row)
73
+ end
74
+ end
75
+
76
+ def test_parse_line
77
+ row = CompactCSV.parse_line("1;2;3", col_sep: ";")
78
+ assert_not_nil(row)
79
+ assert_instance_of(Array, row)
80
+ assert_equal(%w{1 2 3}, row)
81
+
82
+ # shortcut interface
83
+ row = "1;2;3".parse_csv(col_sep: ";")
84
+ assert_not_nil(row)
85
+ assert_instance_of(Array, row)
86
+ assert_equal(%w{1 2 3}, row)
87
+ end
88
+
89
+ def test_parse_line_with_empty_lines
90
+ assert_equal(nil, CompactCSV.parse_line("")) # to signal eof
91
+ assert_equal(Array.new, CompactCSV.parse_line("\n1,2,3"))
92
+ end
93
+
94
+ def test_read_and_readlines
95
+ assert_equal( @expected,
96
+ CompactCSV.read(@path, col_sep: "\t", row_sep: "\r\n") )
97
+ assert_equal( @expected,
98
+ CompactCSV.readlines(@path, col_sep: "\t", row_sep: "\r\n") )
99
+
100
+
101
+ data = CompactCSV.open(@path, col_sep: "\t", row_sep: "\r\n") do |csv|
102
+ csv.read
103
+ end
104
+ assert_equal(@expected, data)
105
+ data = CompactCSV.open(@path, col_sep: "\t", row_sep: "\r\n") do |csv|
106
+ csv.readlines
107
+ end
108
+ assert_equal(@expected, data)
109
+ end
110
+
111
+ def test_table
112
+ table = CompactCSV.table(@path, col_sep: "\t", row_sep: "\r\n")
113
+ assert_instance_of(CompactCSV::Table, table)
114
+ assert_equal([[:"1", :"2", :"3"], [4, 5, nil]], table.to_a)
115
+ end
116
+
117
+ def test_shift # aliased as gets() and readline()
118
+ CompactCSV.open(@path, "rb+", col_sep: "\t", row_sep: "\r\n") do |csv|
119
+ assert_equal(@expected.shift, csv.shift)
120
+ assert_equal(@expected.shift, csv.shift)
121
+ assert_equal(nil, csv.shift)
122
+ end
123
+ end
124
+
125
+ def test_enumerators_are_supported
126
+ CompactCSV.open(@path, col_sep: "\t", row_sep: "\r\n") do |csv|
127
+ enum = csv.each
128
+ assert_instance_of(Enumerator, enum)
129
+ assert_equal(@expected.shift, enum.next)
130
+ end
131
+ end
132
+
133
+ ### Test Write Interface ###
134
+
135
+ def test_generate
136
+ str = CompactCSV.generate do |csv| # default empty String
137
+ assert_instance_of(CompactCSV, csv)
138
+ assert_equal(csv, csv << [1, 2, 3])
139
+ assert_equal(csv, csv << [4, nil, 5])
140
+ end
141
+ assert_not_nil(str)
142
+ assert_instance_of(String, str)
143
+ assert_equal("1,2,3\n4,,5\n", str)
144
+
145
+ CompactCSV.generate(str) do |csv| # appending to a String
146
+ assert_equal(csv, csv << ["last", %Q{"row"}])
147
+ end
148
+ assert_equal(%Q{1,2,3\n4,,5\nlast,"""row"""\n}, str)
149
+ end
150
+
151
+ def test_generate_line
152
+ line = CompactCSV.generate_line(%w{1 2 3}, col_sep: ";")
153
+ assert_not_nil(line)
154
+ assert_instance_of(String, line)
155
+ assert_equal("1;2;3\n", line)
156
+
157
+ # shortcut interface
158
+ line = %w{1 2 3}.to_csv(col_sep: ";")
159
+ assert_not_nil(line)
160
+ assert_instance_of(String, line)
161
+ assert_equal("1;2;3\n", line)
162
+ end
163
+
164
+ def test_write_header_detection
165
+ File.unlink(@path)
166
+
167
+ headers = %w{a b c}
168
+ CompactCSV.open(@path, "w", headers: true) do |csv|
169
+ csv << headers
170
+ csv << %w{1 2 3}
171
+ assert_equal(headers, csv.instance_variable_get(:@headers))
172
+ end
173
+ end
174
+
175
+ def test_write_lineno
176
+ File.unlink(@path)
177
+
178
+ CompactCSV.open(@path, "w") do |csv|
179
+ lines = 20
180
+ lines.times { csv << %w{a b c} }
181
+ assert_equal(lines, csv.lineno)
182
+ end
183
+ end
184
+
185
+ def test_write_hash
186
+ File.unlink(@path)
187
+
188
+ lines = [{a: 1, b: 2, c: 3}, {a: 4, b: 5, c: 6}]
189
+ CompactCSV.open( @path, "wb", headers: true,
190
+ header_converters: :symbol ) do |csv|
191
+ csv << lines.first.keys
192
+ lines.each { |line| csv << line }
193
+ end
194
+ CompactCSV.open( @path, "rb", headers: true,
195
+ converters: :all,
196
+ header_converters: :symbol ) do |csv|
197
+ csv.read.each { |line| assert_equal(lines.shift, line.to_hash) }
198
+ end
199
+ end
200
+
201
+ def test_write_hash_with_string_keys
202
+ File.unlink(@path)
203
+
204
+ lines = [{a: 1, b: 2, c: 3}, {a: 4, b: 5, c: 6}]
205
+ CompactCSV.open( @path, "wb", headers: true ) do |csv|
206
+ csv << lines.first.keys
207
+ lines.each { |line| csv << line }
208
+ end
209
+ CompactCSV.open( @path, "rb", headers: true ) do |csv|
210
+ csv.read.each do |line|
211
+ csv.headers.each_with_index do |header, h|
212
+ keys = line.to_hash.keys
213
+ assert_instance_of(String, keys[h])
214
+ assert_same(header, keys[h])
215
+ end
216
+ end
217
+ end
218
+ end
219
+
220
+ def test_write_hash_with_headers_array
221
+ File.unlink(@path)
222
+
223
+ lines = [{a: 1, b: 2, c: 3}, {a: 4, b: 5, c: 6}]
224
+ CompactCSV.open(@path, "wb", headers: [:b, :a, :c]) do |csv|
225
+ lines.each { |line| csv << line }
226
+ end
227
+
228
+ # test writing fields in the correct order
229
+ File.open(@path, "rb") do |f|
230
+ assert_equal("2,1,3", f.gets.strip)
231
+ assert_equal("5,4,6", f.gets.strip)
232
+ end
233
+
234
+ # test reading CompactCSV with headers
235
+ CompactCSV.open( @path, "rb", headers: [:b, :a, :c],
236
+ converters: :all ) do |csv|
237
+ csv.read.each { |line| assert_equal(lines.shift, line.to_hash) }
238
+ end
239
+ end
240
+
241
+ def test_write_hash_with_headers_string
242
+ File.unlink(@path)
243
+
244
+ lines = [{"a" => 1, "b" => 2, "c" => 3}, {"a" => 4, "b" => 5, "c" => 6}]
245
+ CompactCSV.open(@path, "wb", headers: "b|a|c", col_sep: "|") do |csv|
246
+ lines.each { |line| csv << line }
247
+ end
248
+
249
+ # test writing fields in the correct order
250
+ File.open(@path, "rb") do |f|
251
+ assert_equal("2|1|3", f.gets.strip)
252
+ assert_equal("5|4|6", f.gets.strip)
253
+ end
254
+
255
+ # test reading CompactCSV with headers
256
+ CompactCSV.open( @path, "rb", headers: "b|a|c",
257
+ col_sep: "|",
258
+ converters: :all ) do |csv|
259
+ csv.read.each { |line| assert_equal(lines.shift, line.to_hash) }
260
+ end
261
+ end
262
+
263
+ def test_write_headers
264
+ File.unlink(@path)
265
+
266
+ lines = [{"a" => 1, "b" => 2, "c" => 3}, {"a" => 4, "b" => 5, "c" => 6}]
267
+ CompactCSV.open( @path, "wb", headers: "b|a|c",
268
+ write_headers: true,
269
+ col_sep: "|" ) do |csv|
270
+ lines.each { |line| csv << line }
271
+ end
272
+
273
+ # test writing fields in the correct order
274
+ File.open(@path, "rb") do |f|
275
+ assert_equal("b|a|c", f.gets.strip)
276
+ assert_equal("2|1|3", f.gets.strip)
277
+ assert_equal("5|4|6", f.gets.strip)
278
+ end
279
+
280
+ # test reading CompactCSV with headers
281
+ CompactCSV.open( @path, "rb", headers: true,
282
+ col_sep: "|",
283
+ converters: :all ) do |csv|
284
+ csv.read.each { |line| assert_equal(lines.shift, line.to_hash) }
285
+ end
286
+ end
287
+
288
+ def test_append # aliased add_row() and puts()
289
+ File.unlink(@path)
290
+
291
+ CompactCSV.open(@path, "wb", col_sep: "\t", row_sep: "\r\n") do |csv|
292
+ @expected.each { |row| csv << row }
293
+ end
294
+
295
+ test_shift
296
+
297
+ # same thing using CompactCSV::Row objects
298
+ File.unlink(@path)
299
+
300
+ CompactCSV.open(@path, "wb", col_sep: "\t", row_sep: "\r\n") do |csv|
301
+ @expected.each { |row| csv << CompactCSV::Row.new(Array.new, row) }
302
+ end
303
+
304
+ test_shift
305
+ end
306
+
307
+ ### Test Read and Write Interface ###
308
+
309
+ def test_filter
310
+ assert_respond_to(CompactCSV, :filter)
311
+
312
+ expected = [[1, 2, 3], [4, 5]]
313
+ CompactCSV.filter( "1;2;3\n4;5\n", (result = String.new),
314
+ in_col_sep: ";", out_col_sep: ",",
315
+ converters: :all ) do |row|
316
+ assert_equal(row, expected.shift)
317
+ row.map! { |n| n * 2 }
318
+ row << "Added\r"
319
+ end
320
+ assert_equal("2,4,6,\"Added\r\"\n8,10,\"Added\r\"\n", result)
321
+ end
322
+
323
+ def test_instance
324
+ csv = String.new
325
+
326
+ first = nil
327
+ assert_nothing_raised(Exception) do
328
+ first = CompactCSV.instance(csv, col_sep: ";")
329
+ first << %w{a b c}
330
+ end
331
+
332
+ assert_equal("a;b;c\n", csv)
333
+
334
+ second = nil
335
+ assert_nothing_raised(Exception) do
336
+ second = CompactCSV.instance(csv, col_sep: ";")
337
+ second << [1, 2, 3]
338
+ end
339
+
340
+ assert_equal(first.object_id, second.object_id)
341
+ assert_equal("a;b;c\n1;2;3\n", csv)
342
+
343
+ # shortcuts
344
+ assert_equal(STDOUT, CompactCSV.instance.instance_eval { @io })
345
+ assert_equal(STDOUT, CompactCSV { |new_csv| new_csv.instance_eval { @io } })
346
+ end
347
+
348
+ def test_options_are_not_modified
349
+ opt = {}.freeze
350
+ assert_nothing_raised { CompactCSV.foreach(@path, opt) }
351
+ assert_nothing_raised { CompactCSV.open(@path, opt){} }
352
+ assert_nothing_raised { CompactCSV.parse("", opt) }
353
+ assert_nothing_raised { CompactCSV.parse_line("", opt) }
354
+ assert_nothing_raised { CompactCSV.read(@path, opt) }
355
+ assert_nothing_raised { CompactCSV.readlines(@path, opt) }
356
+ assert_nothing_raised { CompactCSV.table(@path, opt) }
357
+ assert_nothing_raised { CompactCSV.generate(opt){} }
358
+ assert_nothing_raised { CompactCSV.generate_line([], opt) }
359
+ assert_nothing_raised { CompactCSV.filter("", "", opt){} }
360
+ assert_nothing_raised { CompactCSV.instance("", opt) }
361
+ end
362
+ end
@@ -0,0 +1,17 @@
1
+ module DifferentOFS
2
+ module WithDifferentOFS
3
+ def setup
4
+ super
5
+ @ofs, $, = $,, "-"
6
+ end
7
+ def teardown
8
+ $, = @ofs
9
+ super
10
+ end
11
+ end
12
+
13
+ def self.extended(klass)
14
+ super(klass)
15
+ klass.const_set(:DifferentOFS, Class.new(klass).class_eval {include WithDifferentOFS}).name
16
+ end
17
+ end
@@ -0,0 +1,5 @@
1
+ require 'coveralls'
2
+ Coveralls.wear!
3
+
4
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
5
+ require 'compact_csv'
metadata ADDED
@@ -0,0 +1,124 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: compact_csv
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - NAKANO Ryusuke
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-12-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.5'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: coveralls
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: Memory efficient CSV
70
+ email:
71
+ - rsk.nakano@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".gitignore"
77
+ - ".rspec"
78
+ - ".travis.yml"
79
+ - Gemfile
80
+ - LICENSE.txt
81
+ - README.md
82
+ - Rakefile
83
+ - compact_csv.gemspec
84
+ - lib/compact_csv.rb
85
+ - lib/compact_csv/version.rb
86
+ - spec/compact_csv_spec.rb
87
+ - spec/data/sample.csv
88
+ - spec/original_csv_tests/README.md
89
+ - spec/original_csv_tests/base.rb
90
+ - spec/original_csv_tests/test_interface.rb
91
+ - spec/original_csv_tests/with_different_ofs.rb
92
+ - spec/spec_helper.rb
93
+ homepage: https://github.com/rnakano/compact_csv
94
+ licenses:
95
+ - MIT
96
+ metadata: {}
97
+ post_install_message:
98
+ rdoc_options: []
99
+ require_paths:
100
+ - lib
101
+ required_ruby_version: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ required_rubygems_version: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ requirements: []
112
+ rubyforge_project:
113
+ rubygems_version: 2.4.5.1
114
+ signing_key:
115
+ specification_version: 4
116
+ summary: Memory efficient CSV
117
+ test_files:
118
+ - spec/compact_csv_spec.rb
119
+ - spec/data/sample.csv
120
+ - spec/original_csv_tests/README.md
121
+ - spec/original_csv_tests/base.rb
122
+ - spec/original_csv_tests/test_interface.rb
123
+ - spec/original_csv_tests/with_different_ofs.rb
124
+ - spec/spec_helper.rb