rubytree 0.9.7 → 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.
data/rubytree.gemspec CHANGED
@@ -1,55 +1,57 @@
1
- # -*- encoding: utf-8 -*-
2
1
  #
3
2
  # gemspec for the rubytree gem.
4
3
  #
5
4
  # Author:: Anupam Sengupta (anupamsg@gmail.com)
6
5
  #
7
- # Copyright (c) 2012, 2013, 2014, 2015 Anupam Sengupta
8
- # All rights reserved.
6
+ # Copyright (c) 2012-2022 Anupam Sengupta. All rights reserved.
7
+ #
8
+ # frozen_string_literal: true
9
9
 
10
- $:.unshift File.expand_path("../lib", __FILE__)
11
- require "tree/version"
10
+ require './lib/tree/version'
12
11
 
13
12
  Gem::Specification.new do |s|
14
13
  s.name = 'rubytree'
15
- s.date = '2015-12-31'
16
14
  s.version = Tree::VERSION
17
- s.license = 'BSD'
18
-
15
+ s.license = 'BSD-3-Clause-Clear'
16
+ # NOTE: s.date should NOT be assigned. It is automatically set to pkg date.
19
17
  s.platform = Gem::Platform::RUBY
20
18
  s.author = 'Anupam Sengupta'
21
19
  s.email = 'anupamsg@gmail.com'
22
20
  s.homepage = 'http://rubytree.anupamsg.me'
23
21
 
24
- s.required_ruby_version = '>=1.8.7'
22
+ s.required_ruby_version = '>=2.6'
25
23
 
26
- s.summary = %q{A generic tree data structure.}
27
- s.description = <<-EOF
24
+ s.summary = 'A generic tree data structure for Ruby.'
28
25
 
29
- RubyTree is a pure Ruby implementation of the generic tree data structure. It
30
- provides a node-based model to store named nodes in the tree, and provides
31
- simple APIs to access, modify and traverse the structure.
26
+ s.description = <<-END_DESC
27
+ RubyTree is a pure Ruby implementation of the generic tree data
28
+ structure. It provides a node-based model to store named nodes in the tree,
29
+ and provides simple APIs to access, modify and traverse the structure.
32
30
 
33
- The implementation is node-centric, where individual nodes in the tree are the
34
- primary structural elements. All common tree-traversal methods (pre-order,
35
- post-order, and breadth-first) are supported.
31
+ The implementation is node-centric, where individual nodes in the tree are
32
+ the primary structural elements. All common tree-traversal methods
33
+ (pre-order, post-order, and breadth-first) are supported.
36
34
 
37
- The library mixes in the Enumerable and Comparable modules to allow access to
38
- the tree as a standard collection (iteration, comparison, etc.).
35
+ The library mixes in the Enumerable and Comparable modules to allow access
36
+ to the tree as a standard collection (iteration, comparison, etc.).
39
37
 
40
38
  A Binary tree is also provided, which provides the in-order traversal in
41
39
  addition to the other methods.
42
40
 
43
- RubyTree supports importing from, and exporting to JSON, and also supports the
44
- Ruby's standard object marshaling.
41
+ RubyTree supports importing from, and exporting to JSON, and also supports
42
+ the Ruby's standard object marshaling.
45
43
 
46
44
  This is a BSD licensed open source project, and is hosted at
47
- http://github.com/evolve75/RubyTree, and is available as a standard gem from
48
- http://rubygems.org/gems/rubytree.
45
+ <https://github.com/evolve75/RubyTree>, and is available as a standard gem
46
+ from <https://rubygems.org/gems/rubytree>.
47
+
48
+ The home page for RubyTree is at <http://rubytree.anupamsg.me>.
49
49
 
50
- The home page for RubyTree is at http://rubytree.anupamsg.me.
50
+ END_DESC
51
51
 
52
- EOF
52
+ s.metadata = {
53
+ 'rubygems_mfa_required' => 'true'
54
+ }
53
55
 
54
56
  s.files = Dir['lib/**/*.rb'] # The actual code
55
57
  s.files += Dir['[A-Z]*'] # Various documentation files
@@ -57,34 +59,55 @@ Gem::Specification.new do |s|
57
59
  s.files += Dir['spec/**/*.rb'] # Rspec Test cases
58
60
  s.files += Dir['examples/**/*.rb'] # Examples
59
61
 
60
- s.files += ['.gemtest'] # Support for gem-test
62
+ # @todo: Check if this is really needed.
63
+ s.files += ['.gemtest'] # Support for gem-test
61
64
 
62
65
  s.require_paths = ['lib']
63
66
 
64
67
  s.test_files = Dir.glob('test/**/test_*.rb')
65
68
 
66
- s.extra_rdoc_files = ['README.md', 'LICENSE.md',
67
- 'API-CHANGES.rdoc', 'History.rdoc']
68
- s.rdoc_options = ["--title", "Rubytree Documentation", "--quiet"]
69
+ s.extra_rdoc_files = %w[README.md LICENSE.md API-CHANGES.md History.md]
70
+ s.rdoc_options = ['--title', "Rubytree Documentation: #{s.name}-#{s.version}",
71
+ '--main', 'README.md',
72
+ '--quiet']
73
+
74
+ s.add_runtime_dependency 'json', '~> 2.0', '> 2.3.1'
75
+
76
+ # NOTE: Rake is added as a development and test dependency in the Gemfile.
77
+ s.add_development_dependency 'bundler', '~> 2.3'
78
+ s.add_development_dependency 'rake', '~> 13.0'
79
+ s.add_development_dependency 'rdoc', '~> 6.0'
80
+ s.add_development_dependency 'rspec', '~> 3.0', '> 3.10'
81
+ s.add_development_dependency 'rtagstask', '~> 0.0.4'
82
+ s.add_development_dependency 'rubocop', '~> 1.0'
83
+ s.add_development_dependency 'rubocop-rake', '~> 0.0'
84
+ s.add_development_dependency 'rubocop-rspec', '~> 2.0'
85
+ s.add_development_dependency 'test-unit', '~> 3.0'
86
+ s.add_development_dependency 'yard', '~> 0.0', '>= 0.9.20'
87
+
88
+ s.post_install_message = <<-END_MESSAGE
89
+ ========================================================================
90
+ Thank you for installing RubyTree.
69
91
 
70
- s.add_runtime_dependency 'structured_warnings' , '~> 0.2'
71
- s.add_runtime_dependency 'json' , '~> 1.8'
92
+ Note::
72
93
 
73
- # Note: Rake is added as a development and test dependency in the Gemfile.
74
- s.add_development_dependency 'bundler' , '~> 1.7'
75
- s.add_development_dependency 'rdoc' , '~> 4.2'
76
- s.add_development_dependency 'yard' , '~> 0.8'
77
- s.add_development_dependency 'rtagstask' , '~> 0.0'
78
- s.add_development_dependency 'rspec' , '~> 3.4'
94
+ - 2.0.0 is a major release with BREAKING API changes.
95
+ See `API-CHANGES.md` for details.
79
96
 
80
- s.post_install_message = <<-EOF
81
- ========================================================================
82
- Thank you for installing RubyTree.
97
+ - `Tree::TreeNode#depth` method has been removed (it was broken).
83
98
 
84
- Note:: As of 0.9.5, the Tree::TreeNode#add method has 'move' semantics.
99
+ - Support for `CamelCase` methods names has bee removed.
85
100
 
86
- Details of the API changes are documented in the API-CHANGES file.
87
- ========================================================================
88
- EOF
101
+ - The predicate methods no longer have `is_` or `has_` prefixes. However,
102
+ aliases with these prefixes exist to support existing client code.
103
+
104
+ - Use of integers as node names does not require the optional
105
+ `num_as_name` flag.
89
106
 
107
+ - `structured_warnings` is no longer a dependency.
108
+
109
+ - Explicit support for rbx Ruby has been removed.
110
+
111
+ ========================================================================
112
+ END_MESSAGE
90
113
  end
data/spec/spec_helper.rb CHANGED
@@ -3,8 +3,10 @@
3
3
  # spec_helper.rb
4
4
  #
5
5
  # Author: Anupam Sengupta
6
- # Time-stamp: <2015-12-31 21:00:36 anupam>
7
- # Copyright (C) 2015 Anupam Sengupta <anupamsg@gmail.com>
6
+ # Time-stamp: <2022-06-19 22:38:14 anupam>
8
7
  #
8
+ # Copyright (C) 2015, 2022 Anupam Sengupta <anupamsg@gmail.com>
9
+ #
10
+ # frozen_string_literal: true
9
11
 
10
- require "tree"
12
+ require 'tree'
data/spec/tree_spec.rb CHANGED
@@ -3,72 +3,171 @@
3
3
  # tree_spec.rb
4
4
  #
5
5
  # Author: Anupam Sengupta
6
- # Time-stamp: <2015-12-31 22:57:59 anupam>
7
- # Copyright (C) 2015 Anupam Sengupta <anupamsg@gmail.com>
6
+ # Time-stamp: <2022-06-20 22:16:11 anupam>
7
+ # Copyright (C) 2015-2022 Anupam Sengupta <anupamsg@gmail.com>
8
8
  #
9
+ # frozen_string_literal: true
9
10
 
10
- require "rspec"
11
- require "spec_helper"
11
+ require 'rspec'
12
+ require 'spec_helper'
12
13
 
13
- describe Tree do
14
+ class SpecializedTreeNode < Tree::TreeNode; end
14
15
 
15
- shared_examples_for "any detached node" do
16
- it 'should not equal "Object.new"' do
17
- expect(@tree).not_to eq(Object.new)
16
+ describe Tree do
17
+ shared_examples_for 'any detached node' do
18
+ it 'does not equal "Object.new"' do
19
+ expect(tree).not_to eq(Object.new)
18
20
  end
19
- it 'should not equal 1 or any other fixnum' do
20
- expect(@tree).not_to eq(1)
21
+
22
+ it 'does not equal 1 or any other fixnum' do
23
+ expect(tree).not_to eq(1)
21
24
  end
25
+
22
26
  it 'identifies itself as a root node' do
23
- expect(@tree.is_root?).to eq(true)
24
- end
25
- it "does not have a parent node" do
26
- expect(@tree.parent).to eq(nil)
27
+ expect(tree.root?).to be(true)
27
28
  end
28
29
 
29
- end
30
- context "#initialize", "with empty name and nil content" do
31
- before(:each) do
32
- @tree = Tree::TreeNode.new("")
30
+ it 'does not have a parent node' do
31
+ expect(tree.parent).to be_nil
33
32
  end
33
+ end
34
+
35
+ describe '#initialize with empty name and nil content' do
36
+ let(:tree) { Tree::TreeNode.new('') }
37
+
34
38
  it 'creates the tree node with name as ""' do
35
- expect(@tree.name).to eq("")
39
+ expect(tree.name).to eq('')
36
40
  end
41
+
37
42
  it "has 'nil' content" do
38
- expect(@tree.content).to eq(nil)
43
+ expect(tree.content).to be_nil
39
44
  end
40
45
 
41
- it_behaves_like "any detached node"
46
+ it_behaves_like 'any detached node'
42
47
  end
43
48
 
44
- context "#initialize", "with name 'A' and nil content" do
45
- before(:each) do
46
- @tree = Tree::TreeNode.new("A")
47
- end
49
+ describe "#initialize with name 'A' and nil content" do
50
+ let(:tree) { Tree::TreeNode.new('A') }
48
51
 
49
52
  it 'creates the tree node with name as "A"' do
50
- expect(@tree.name).to eq("A")
53
+ expect(tree.name).to eq('A')
51
54
  end
55
+
52
56
  it "has 'nil' content" do
53
- expect(@tree.content).to eq(nil)
57
+ expect(tree.content).to be_nil
54
58
  end
55
59
 
56
- it_behaves_like "any detached node"
60
+ it_behaves_like 'any detached node'
57
61
  end
58
62
 
59
- context "#initialize", "with node name 'A' and some content" do
60
- before(:each) do
61
- @sample = "sample"
62
- @tree = Tree::TreeNode.new("A", @sample)
63
- end
63
+ describe "#initialize with node name 'A' and some content" do
64
+ sample = 'some content'
65
+ let(:tree) { Tree::TreeNode.new('A', sample) }
64
66
 
65
67
  it 'creates the tree node with name as "A"' do
66
- expect(@tree.name).to eq("A")
68
+ expect(tree.name).to eq('A')
69
+ end
70
+
71
+ it "has some content #{sample}" do
72
+ expect(tree.content).to eq(sample)
73
+ end
74
+
75
+ it_behaves_like 'any detached node'
76
+ end
77
+
78
+ describe 'comparison' do
79
+ let(:node1) { Tree::TreeNode.new('a') }
80
+ let(:node2) { SpecializedTreeNode.new('b') }
81
+
82
+ it 'allows comparison of specialized tree nodes' do
83
+ expect(node1 <=> node2).to be_eql(-1)
84
+ end
85
+
86
+ it 'does not allow comparison with nil' do
87
+ expect(node1 <=> nil).to be_nil
88
+ end
89
+
90
+ it 'does not allow comparison with other objects' do
91
+ expect(node1 <=> 'c').to be_nil
92
+ end
93
+ end
94
+
95
+ describe 'serialization' do
96
+ let(:serialized_node1) { Marshal.dump(SpecializedTreeNode.new('a')) }
97
+ let(:serialized_node2) { Marshal.dump(Tree::TreeNode.new('b')) }
98
+ let(:tree) do
99
+ SpecializedTreeNode.new('root').tap do |root|
100
+ root << SpecializedTreeNode.new('a')
101
+ root << Tree::TreeNode.new('b')
102
+ end
103
+ end
104
+ let(:serialized_tree) { Marshal.dump(tree) }
105
+
106
+ it 'parses the serialized specialized tree node correctly (root)' do
107
+ expect(Marshal.load(serialized_tree)).to be_a(SpecializedTreeNode)
108
+ end
109
+
110
+ it 'parses the serialized specialized tree node correctly (child)' do
111
+ expect(Marshal.load(serialized_tree).children.first).to \
112
+ be_a(SpecializedTreeNode)
113
+ end
114
+
115
+ it 'parses the serialized tree node correctly' do
116
+ expect(Marshal.load(serialized_node2)).to be_a(Tree::TreeNode)
117
+ end
118
+ end
119
+
120
+ shared_examples_for 'any cloned node' do
121
+ it 'is equal to the original' do
122
+ expect(clone).to eq tree
123
+ end
124
+
125
+ it 'is not identical to the original' do
126
+ expect(clone).not_to be tree
127
+ end
128
+ end
129
+
130
+ describe '#detached_copy', 'Without content' do
131
+ let(:tree) { Tree::TreeNode.new('A', nil) }
132
+ let(:clone) { tree.detached_copy }
133
+
134
+ it_behaves_like 'any cloned node'
135
+ end
136
+
137
+ describe '#detached_copy with clonable content' do
138
+ let(:tree) { Tree::TreeNode.new('A', 'clonable content') }
139
+ let(:clone) { tree.detached_copy }
140
+
141
+ it 'makes a clone of the content' do
142
+ expect(clone.content).to eq tree.content
143
+ end
144
+
145
+ it 'is not the same as the original content' do
146
+ expect(clone.content).not_to be tree.content
147
+ end
148
+
149
+ it_behaves_like 'any cloned node'
150
+ end
151
+
152
+ describe '#detached_copy with unclonable content' do
153
+ let(:tree) { Tree::TreeNode.new('A', :unclonable_content) }
154
+ let(:clone) { tree.detached_copy }
155
+
156
+ it 'retains the original content' do
157
+ expect(clone.content).to be tree.content
67
158
  end
68
- it "has some content #{@sample}" do
69
- expect(@tree.content).to eq(@sample)
159
+
160
+ it_behaves_like 'any cloned node'
161
+ end
162
+
163
+ describe '#detached_copy with false as content' do
164
+ let(:tree) { Tree::TreeNode.new('A', false) }
165
+ let(:clone) { tree.detached_copy }
166
+
167
+ it 'retains the original content' do
168
+ expect(clone.content).to be tree.content
70
169
  end
71
170
 
72
- it_behaves_like "any detached node"
171
+ it_behaves_like 'any cloned node'
73
172
  end
74
173
  end
data/test/run_test.rb CHANGED
@@ -3,8 +3,8 @@
3
3
  # run_test.rb:: Run all the tests from the Ruby command line.
4
4
  #
5
5
  # Author: Anupam Sengupta
6
- # Time-stamp: <2014-01-03 21:15:37 anupam>
7
- # Copyright (C) 2014 Anupam Sengupta <anupamsg@gmail.com>
6
+ # Time-stamp: <2022-06-19 22:44:56 anupam>
7
+ # Copyright (C) 2014, 2022 Anupam Sengupta <anupamsg@gmail.com>
8
8
  #
9
9
  # Redistribution and use in source and binary forms, with or without modification,
10
10
  # are permitted provided that the following conditions are met:
@@ -31,14 +31,15 @@
31
31
  # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32
32
  # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
33
  #
34
+ # frozen_string_literal: true
34
35
 
35
- base_dir = File.expand_path(File.join(File.dirname(__FILE__), ".."))
36
- lib_dir = File.join(base_dir, "lib")
37
- test_dir = File.join(base_dir, "test")
36
+ base_dir = File.expand_path(File.join(File.dirname(__FILE__), '..'))
37
+ lib_dir = File.join(base_dir, 'lib')
38
+ test_dir = File.join(base_dir, 'test')
38
39
 
39
40
  $LOAD_PATH.unshift(lib_dir)
40
41
 
41
- if ENV["COVERAGE"]
42
+ if ENV['COVERAGE']
42
43
  begin
43
44
  require 'simplecov'
44
45
  require 'coveralls'
@@ -51,10 +52,10 @@ if ENV["COVERAGE"]
51
52
  add_group 'Internal Utilities', '/lib/tree/utils/.*.rb'
52
53
  end
53
54
  rescue LoadError => e
54
- puts "Could not load simplecov; continuing without code coverage"
55
+ puts "Could not load simplecov; continuing without code coverage #{e.cause}"
55
56
  end
56
57
  end
57
58
 
58
59
  require 'test/unit'
59
60
 
60
- exit Test::Unit::AutoRunner.run(true, test_dir)
61
+ Test::Unit::AutoRunner.run(true, test_dir)