tsv 0.0.3 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: dccfc4465a2459edbb3847afe9a97085a30c246a
4
- data.tar.gz: 8f6c86869945c3bae1a9653b91fc7c7b5fdfa0f0
3
+ metadata.gz: 901a06d59683d6bb8df05d6298bf0157ef09dac2
4
+ data.tar.gz: 76f1f731eb6d4bf236bfac4349c503fa5b734296
5
5
  SHA512:
6
- metadata.gz: 0151a2a89fc5141711095bdc0f2f0fcb03de963947802cee913eeca5a19acfa18574c38978fa68f3012603399074bf68b13d079ee78979609f0e26fa3033b5ab
7
- data.tar.gz: f6f18e7654c47a5a16721c4885e363beb2de78709806211a87da9b7684f86ddeff014c16df0ec3df8025463bce25df5606cfc4a10426c2d1831963c1fee10a9c
6
+ metadata.gz: 6b68ee097e32ef0c00b4066b1bcc4cc21efccde77a7af13661a1b7c108387ff1081fa4cd1a772eb4cb63871c2ff95baa786f21f262be04e2f8e30e1774063f21
7
+ data.tar.gz: 2643de24f05a2f19a0302954007720664f4af744266ddc0252152b467d1debecd8c4fa4f87010586662a5b6951ed68ab7764b4ab651baa1ccfebf1b85001fdbe
@@ -9,7 +9,8 @@ rvm:
9
9
  - 2.0.0
10
10
  - 2.1.1
11
11
  - 2.1.2
12
- - rbx-2.2.6
12
+ - 2.2.0
13
+ - rbx-2.5.1
13
14
  - jruby
14
15
 
15
16
  # Part of test suite - building gem and trying to require it via ruby -e
@@ -18,6 +19,6 @@ script: >
18
19
  rake build&&gem install pkg/tsv*.gem&&ruby -e 'require "tsv"; TSV.parse_file("spec/fixtures/example.tsv").to_a'&&rake
19
20
 
20
21
  matrix:
21
- allow_failures:
22
- - rvm: rbx-2.2.6
22
+ allow_failures:
23
+ - rvm: rbx-2.5.1
23
24
  - rvm: jruby
@@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file.
3
3
 
4
4
  ## [Unreleased][unreleased]
5
5
 
6
+ ## [1.0.0] - 2015-02-14
7
+ ### Changed
8
+ - Reworked Cyclist into Table
9
+
6
10
  ## [0.0.3] - 2014-12-26
7
11
  ### Fixed
8
12
  - Fixed case with empty column contents in TSV
@@ -12,13 +16,14 @@ All notable changes to this project will be documented in this file.
12
16
 
13
17
  ## [0.0.2] - 2014-08-13
14
18
  ### Changed
15
- - Internal refactorings
19
+ - Internal refactoring
16
20
 
17
21
  ### Added
18
22
  - Testing built gem integrity via CI
19
23
 
20
24
  Changelog format taken from [keep-a-changelog](https://github.com/olivierlacan/keep-a-changelog)
21
25
 
22
- [unreleased]: https://github.com/mimimi/ruby-tsv/compare/v0.0.3...master
26
+ [unreleased]: https://github.com/mimimi/ruby-tsv/compare/v1.0.0...master
27
+ [1.0.0]: https://github.com/mimimi/ruby-tsv/compare/v0.0.3...v1.0.0
23
28
  [0.0.3]: https://github.com/mimimi/ruby-tsv/compare/v0.0.2...v0.0.3
24
29
  [0.0.2]: https://github.com/mimimi/ruby-tsv/compare/v0.0.1...v0.0.2
data/Gemfile CHANGED
@@ -3,7 +3,9 @@ source 'https://rubygems.org'
3
3
  # Specify your gem's dependencies in tsv.gemspec
4
4
  gemspec
5
5
 
6
- gem "codeclimate-test-reporter", group: :test, require: nil
7
- gem "rake"
8
- gem "rspec"
9
- gem "pry"
6
+ group "test" do
7
+ gem "codeclimate-test-reporter", require: nil
8
+ gem "rake"
9
+ gem "rspec", "~> 3.1.0"
10
+ gem "pry"
11
+ end
data/README.md CHANGED
@@ -27,16 +27,21 @@ Or install it yourself as:
27
27
 
28
28
  #### TSV::parse
29
29
 
30
- `TSV.parse` accepts TSV as a whole string, returning lazy enumerator, yielding TSV::Row objects on demand
30
+ `TSV.parse` accepts basically anything that can enumerate over lines, for example:
31
+
32
+ * TSV as a whole string
33
+ * any IO object - a TSV file pre-opened with `File.open`, `StringIO` buffer containing TSV data, etc
34
+
35
+ It returns a lazy enumerator, yielding TSV::Row objects on demand.
31
36
 
32
37
  #### TSV::parse_file
33
38
 
34
39
  `TSV.parse_file` accepts path to TSV file, returning lazy enumerator, yielding TSV::Row objects on demand
35
40
  `TSV.parse_file` is also aliased as `[]`, allowing for `TSV[filename]` syntax
36
41
 
37
- #### TSV::Cyclist
42
+ #### TSV::Table
38
43
 
39
- While TSV specification requires headers, popular use doesn't necessarily adhere. In order to cope both `TSV::parse` and `TSV::parse_file` return Cyclist objects, that apart from acting as enumerators expose two additional methods: `#with_headers` and `#without_headers`. Neither method preserves read position by design.
44
+ While TSV specification requires headers, popular use doesn't necessarily adhere. In order to cope both `TSV::parse` and `TSV::parse_file` return `TSV::Table` object, that apart from acting as enumerator exposes two additional methods: `#with_headers` and `#without_headers`. Neither method preserves read position by design.
40
45
 
41
46
  #### TSV::Row
42
47
 
data/lib/tsv.rb CHANGED
@@ -2,17 +2,17 @@ require 'forwardable'
2
2
 
3
3
  require "tsv/version"
4
4
  require "tsv/row"
5
- require "tsv/cyclist"
5
+ require "tsv/table"
6
6
 
7
7
  module TSV
8
8
  extend self
9
9
 
10
10
  def parse(content, opts = {}, &block)
11
- TSV::StringCyclist.new(content, opts, &block)
11
+ TSV::Table.new(content, opts, &block)
12
12
  end
13
-
13
+
14
14
  def parse_file(filename, opts = {}, &block)
15
- TSV::FileCyclist.new(filename, opts, &block)
15
+ TSV::Table.new(File.new(filename, 'r'), opts, &block)
16
16
  end
17
17
 
18
18
  alias :[] :parse_file
@@ -1,5 +1,5 @@
1
1
  module TSV
2
- class Cyclist
2
+ class Table
3
3
  extend Forwardable
4
4
 
5
5
  def_delegators :enumerator, *Enumerator.instance_methods(false)
@@ -8,8 +8,8 @@ module TSV
8
8
  attr_accessor :source, :header
9
9
 
10
10
  def initialize(source, params = {}, &block)
11
- self.header = params.fetch(:header, true)
12
- self.source = source.to_s
11
+ self.header = params.fetch(:header, true)
12
+ self.source = source
13
13
  self.enumerator.each(&block) if block_given?
14
14
  end
15
15
 
@@ -44,6 +44,10 @@ module TSV
44
44
  end
45
45
  end
46
46
 
47
+ def data_enumerator
48
+ source.each_line
49
+ end
50
+
47
51
  protected
48
52
 
49
53
  def generate_row_from(str)
@@ -54,18 +58,4 @@ module TSV
54
58
  (0...example_line.length).to_a.map(&:to_s)
55
59
  end
56
60
  end
57
-
58
- class FileCyclist < Cyclist
59
- alias :filepath :source
60
-
61
- def data_enumerator
62
- File.new(self.source).each_line
63
- end
64
- end
65
-
66
- class StringCyclist < Cyclist
67
- def data_enumerator
68
- source.each_line
69
- end
70
- end
71
61
  end
@@ -1,3 +1,3 @@
1
1
  module TSV
2
- VERSION = "0.0.3"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -1,4 +1,14 @@
1
- shared_examples_for "Cyclist" do
1
+ require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper.rb')
2
+
3
+ describe TSV::Table do
4
+ let(:source) { IO.read(File.join(File.dirname(__FILE__), '..', '..', 'fixtures', filename)) }
5
+ let(:filename) { 'example.tsv' }
6
+
7
+ let(:header) { true }
8
+ let(:parameters) { { header: header } }
9
+
10
+ subject(:table) { TSV::Table.new(source, parameters) }
11
+
2
12
  describe "::new" do
3
13
  it "initializes header to true by default" do
4
14
  expect(subject.header).to be true
@@ -25,8 +35,8 @@ shared_examples_for "Cyclist" do
25
35
  end
26
36
 
27
37
  describe "#enumerator" do
28
- it { expect(cyclist.enumerator).to be_a_kind_of(Enumerator) }
29
- subject { cyclist.enumerator.to_a }
38
+ it { expect(table.enumerator).to be_a_kind_of(Enumerator) }
39
+ subject { table.enumerator.to_a }
30
40
 
31
41
  context "string is empty" do
32
42
  let(:filename) { 'empty.tsv' }
@@ -83,17 +93,17 @@ shared_examples_for "Cyclist" do
83
93
  end
84
94
 
85
95
  describe "#with_header" do
86
- subject { cyclist.with_header }
87
-
88
- it "returns a Cyclist with header option set to true" do
96
+ subject { table.with_header }
97
+
98
+ it "returns a Table with header option set to true" do
89
99
  expect(subject.header).to be true
90
100
  end
91
101
  end
92
102
 
93
103
  describe "#without_header" do
94
- subject { cyclist.without_header }
104
+ subject { table.without_header }
95
105
 
96
- it "returns a Cyclist with header option set to false" do
106
+ it "returns a Table with header option set to false" do
97
107
  expect(subject.header).to be false
98
108
  end
99
109
  end
@@ -101,9 +111,9 @@ shared_examples_for "Cyclist" do
101
111
  describe "enumerator interfaces" do
102
112
  ( Enumerable.instance_methods(false) + Enumerator.instance_methods(false) ).each do |name|
103
113
  it "delegates #{name} to enumerator" do
104
- expect(cyclist.enumerator).to receive(name)
105
- cyclist.send(name)
114
+ expect(table.enumerator).to receive(name)
115
+ table.send(name)
106
116
  end
107
117
  end
108
118
  end
109
- end
119
+ end
@@ -5,28 +5,55 @@ describe TSV do
5
5
 
6
6
  describe "#parse" do
7
7
  let(:header) { nil }
8
- let(:content) { IO.read(File.join(File.dirname(__FILE__), '..', 'fixtures', filename)) }
9
8
  let(:parameters) { { header: header } }
10
9
 
11
- subject { TSV.parse(content, parameters) }
10
+ context "given a string with content" do
11
+ let(:content) { IO.read(File.join(File.dirname(__FILE__), '..', 'fixtures', filename)) }
12
12
 
13
- it "returns String Cyclist initialized with given data" do
14
- expect(subject).to be_a TSV::StringCyclist
15
- expect(subject.source).to eq(content)
13
+ subject { TSV.parse(content, parameters) }
14
+
15
+ it "returns Table initialized with given data" do
16
+ expect(subject).to be_a TSV::Table
17
+ expect(subject.source).to eq(content)
18
+ end
19
+
20
+ context "when block is given" do
21
+ it "passes block to Table" do
22
+ data = []
23
+
24
+ TSV.parse(content) do |i|
25
+ data.push i
26
+ end
27
+
28
+ headers = %w{first second third}
29
+ expect(data).to eq [ TSV::Row.new( ['0', '1', '2'], headers ),
30
+ TSV::Row.new( ['one', 'two', 'three'], headers ),
31
+ TSV::Row.new( ['weird data', 's@mthin#', 'else'], headers ) ]
32
+ end
33
+ end
16
34
  end
17
35
 
18
- context "when block is given" do
19
- it "passes block to Cyclist" do
36
+ context "given a opened IO object" do
37
+ let(:content) { File.open(File.join(File.dirname(__FILE__), '..', 'fixtures', filename), 'r') }
38
+
39
+ subject { TSV.parse(content, parameters) }
40
+
41
+ it "returns Table initialized with given data" do
42
+ expect(subject).to be_a TSV::Table
43
+ expect(subject.source).to eq(content)
44
+ end
45
+
46
+ it "can properly parse file" do
20
47
  data = []
21
-
22
- TSV.parse(content) do |i|
48
+
49
+ TSV.parse(content).each do |i|
23
50
  data.push i
24
51
  end
25
52
 
26
53
  headers = %w{first second third}
27
54
  expect(data).to eq [ TSV::Row.new( ['0', '1', '2'], headers ),
28
- TSV::Row.new( ['one', 'two', 'three'], headers ),
29
- TSV::Row.new( ['weird data', 's@mthin#', 'else'], headers ) ]
55
+ TSV::Row.new( ['one', 'two', 'three'], headers ),
56
+ TSV::Row.new( ['weird data', 's@mthin#', 'else'], headers ) ]
30
57
  end
31
58
  end
32
59
  end
@@ -36,13 +63,16 @@ describe TSV do
36
63
 
37
64
  subject { TSV.parse_file tsv_path }
38
65
 
39
- it "returns Cyclist object initialized with given filepath" do
40
- expect(subject).to be_a TSV::FileCyclist
41
- expect(subject.filepath).to eq tsv_path
66
+ context "when no block is given" do
67
+ it "returns Table initialized with File object" do
68
+ expect(subject).to be_a TSV::Table
69
+ expect(subject.source).to be_kind_of(File)
70
+ expect(subject.source.path).to eq(tsv_path)
71
+ end
42
72
  end
43
73
 
44
74
  context "when block is given" do
45
- it "passes block to Cyclist" do
75
+ it "passes block to Table" do
46
76
  data = []
47
77
 
48
78
  TSV.parse_file(tsv_path) do |i|
@@ -55,5 +85,27 @@ describe TSV do
55
85
  TSV::Row.new( ['weird data', 's@mthin#', 'else'], headers ) ]
56
86
  end
57
87
  end
88
+
89
+ context "when accessing unavailable files" do
90
+ subject { lambda { TSV.parse_file(tsv_path).to_a } }
91
+
92
+ context "when file is not found" do
93
+ let(:tsv_path) { "AManThatWasntThere.tsv" }
94
+
95
+ it "returns FileNotFoundException" do
96
+ expect(subject).to raise_error(Errno::ENOENT)
97
+ end
98
+ end
99
+ end
100
+
101
+ describe "intermediate file handle" do
102
+ it "raises IOError on write attempt" do
103
+ tempfile = Tempfile.new('tsv_test')
104
+ handle = TSV.parse_file(tempfile.path).source
105
+
106
+ expect{ handle.puts('test string please ignore') }.to raise_error(IOError, 'not opened for writing')
107
+ end
108
+ end
109
+
58
110
  end
59
111
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tsv
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dmytro Soltys
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-12-26 00:00:00.000000000 Z
12
+ date: 2015-02-14 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: Streamed TSV parser
15
15
  email:
@@ -28,19 +28,17 @@ files:
28
28
  - README.md
29
29
  - Rakefile
30
30
  - lib/tsv.rb
31
- - lib/tsv/cyclist.rb
32
31
  - lib/tsv/row.rb
32
+ - lib/tsv/table.rb
33
33
  - lib/tsv/version.rb
34
34
  - spec/fixtures/broken.tsv
35
35
  - spec/fixtures/empty-trailing.tsv
36
36
  - spec/fixtures/empty.tsv
37
37
  - spec/fixtures/example.tsv
38
- - spec/lib/tsv/file_cyclist_spec.rb
39
38
  - spec/lib/tsv/row_spec.rb
40
- - spec/lib/tsv/string_cyclist_spec.rb
39
+ - spec/lib/tsv/table_spec.rb
41
40
  - spec/lib/tsv_spec.rb
42
41
  - spec/spec_helper.rb
43
- - spec/support/cyclist_generic.rb
44
42
  - spec/tsv_integration_spec.rb
45
43
  - tsv.gemspec
46
44
  homepage: ''
@@ -73,10 +71,8 @@ test_files:
73
71
  - spec/fixtures/empty-trailing.tsv
74
72
  - spec/fixtures/empty.tsv
75
73
  - spec/fixtures/example.tsv
76
- - spec/lib/tsv/file_cyclist_spec.rb
77
74
  - spec/lib/tsv/row_spec.rb
78
- - spec/lib/tsv/string_cyclist_spec.rb
75
+ - spec/lib/tsv/table_spec.rb
79
76
  - spec/lib/tsv_spec.rb
80
77
  - spec/spec_helper.rb
81
- - spec/support/cyclist_generic.rb
82
78
  - spec/tsv_integration_spec.rb
@@ -1,34 +0,0 @@
1
- require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper.rb')
2
-
3
- describe TSV::FileCyclist do
4
- let(:tsv_path) { File.join(File.dirname(__FILE__), '..', '..', 'fixtures', filename) }
5
- let(:source) { tsv_path }
6
- let(:filename) { 'example.tsv' }
7
-
8
- let(:header) { true }
9
- let(:parameters) { { header: header } }
10
-
11
- subject(:cyclist) { TSV::FileCyclist.new(source, parameters) }
12
-
13
- it_behaves_like "Cyclist"
14
-
15
- describe "accessing unavailable files" do
16
- subject { lambda { TSV::FileCyclist.new(tsv_path).to_a } }
17
-
18
- context "when file is not found" do
19
- let(:tsv_path) { "AManThatWasntThere.tsv" }
20
-
21
- it "returns FileNotFoundException" do
22
- expect(subject).to raise_error(Errno::ENOENT)
23
- end
24
- end
25
-
26
- context "when filename is nil" do
27
- let(:tsv_path) { nil }
28
-
29
- it "returns FileNameInvalidException" do
30
- expect(subject).to raise_error(Errno::ENOENT)
31
- end
32
- end
33
- end
34
- end
@@ -1,13 +0,0 @@
1
- require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper.rb')
2
-
3
- describe TSV::StringCyclist do
4
- let(:source) { IO.read(File.join(File.dirname(__FILE__), '..', '..', 'fixtures', filename)) }
5
- let(:filename) { 'example.tsv' }
6
-
7
- let(:header) { true }
8
- let(:parameters) { { header: header } }
9
-
10
- subject(:cyclist) { TSV::StringCyclist.new(source, parameters) }
11
-
12
- it_behaves_like "Cyclist"
13
- end