compact_csv 0.0.1

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 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