tsv 0.0.3 → 1.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 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