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.
- checksums.yaml +5 -5
- data/API-CHANGES.md +153 -0
- data/Gemfile +2 -13
- data/Gemfile.lock +60 -61
- data/History.md +410 -0
- data/LICENSE.md +1 -2
- data/README.md +24 -28
- data/Rakefile +65 -48
- data/TODO.org +19 -15
- data/examples/example_basic.rb +19 -12
- data/lib/rubytree.rb +3 -4
- data/lib/tree/binarytree.rb +27 -27
- data/lib/tree/tree_deps.rb +9 -12
- data/lib/tree/utils/hash_converter.rb +127 -121
- data/lib/tree/utils/json_converter.rb +81 -79
- data/lib/tree/utils/metrics_methods.rb +18 -48
- data/lib/tree/utils/path_methods.rb +15 -17
- data/lib/tree/utils/tree_merge_handler.rb +79 -80
- data/lib/tree/utils/utils.rb +9 -6
- data/lib/tree/version.rb +3 -5
- data/lib/tree.rb +194 -177
- data/rubytree.gemspec +67 -44
- data/spec/spec_helper.rb +5 -3
- data/spec/tree_spec.rb +136 -37
- data/test/run_test.rb +9 -8
- data/test/test_binarytree.rb +86 -105
- data/test/test_rubytree_require.rb +4 -5
- data/test/test_subclassed_node.rb +5 -26
- data/test/test_thread_and_fiber.rb +13 -16
- data/test/test_tree.rb +577 -657
- metadata +142 -55
- data/API-CHANGES.rdoc +0 -99
- data/History.rdoc +0 -303
- data/TAGS +0 -248
- data/gem_graph.png +0 -0
- data/lib/tree/utils/camel_case_method_handler.rb +0 -79
- data/setup.rb +0 -1585
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
|
8
|
-
#
|
6
|
+
# Copyright (c) 2012-2022 Anupam Sengupta. All rights reserved.
|
7
|
+
#
|
8
|
+
# frozen_string_literal: true
|
9
9
|
|
10
|
-
|
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 = '>=
|
22
|
+
s.required_ruby_version = '>=2.6'
|
25
23
|
|
26
|
-
s.summary =
|
27
|
-
s.description = <<-EOF
|
24
|
+
s.summary = 'A generic tree data structure for Ruby.'
|
28
25
|
|
29
|
-
|
30
|
-
|
31
|
-
|
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
|
34
|
-
primary structural elements. All common tree-traversal methods
|
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
|
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
|
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
|
-
|
48
|
-
|
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
|
-
|
50
|
+
END_DESC
|
51
51
|
|
52
|
-
|
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
|
-
|
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 = [
|
67
|
-
|
68
|
-
|
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
|
-
|
71
|
-
s.add_runtime_dependency 'json' , '~> 1.8'
|
92
|
+
Note::
|
72
93
|
|
73
|
-
|
74
|
-
|
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
|
-
|
81
|
-
========================================================================
|
82
|
-
Thank you for installing RubyTree.
|
97
|
+
- `Tree::TreeNode#depth` method has been removed (it was broken).
|
83
98
|
|
84
|
-
|
99
|
+
- Support for `CamelCase` methods names has bee removed.
|
85
100
|
|
86
|
-
|
87
|
-
|
88
|
-
|
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: <
|
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
|
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: <
|
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
|
11
|
-
require
|
11
|
+
require 'rspec'
|
12
|
+
require 'spec_helper'
|
12
13
|
|
13
|
-
|
14
|
+
class SpecializedTreeNode < Tree::TreeNode; end
|
14
15
|
|
15
|
-
|
16
|
-
|
17
|
-
|
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
|
-
|
20
|
-
|
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(
|
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
|
-
|
30
|
-
|
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(
|
39
|
+
expect(tree.name).to eq('')
|
36
40
|
end
|
41
|
+
|
37
42
|
it "has 'nil' content" do
|
38
|
-
expect(
|
43
|
+
expect(tree.content).to be_nil
|
39
44
|
end
|
40
45
|
|
41
|
-
it_behaves_like
|
46
|
+
it_behaves_like 'any detached node'
|
42
47
|
end
|
43
48
|
|
44
|
-
|
45
|
-
|
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(
|
53
|
+
expect(tree.name).to eq('A')
|
51
54
|
end
|
55
|
+
|
52
56
|
it "has 'nil' content" do
|
53
|
-
expect(
|
57
|
+
expect(tree.content).to be_nil
|
54
58
|
end
|
55
59
|
|
56
|
-
it_behaves_like
|
60
|
+
it_behaves_like 'any detached node'
|
57
61
|
end
|
58
62
|
|
59
|
-
|
60
|
-
|
61
|
-
|
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(
|
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
|
-
|
69
|
-
|
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
|
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: <
|
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,
|
37
|
-
test_dir = File.join(base_dir,
|
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[
|
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
|
-
|
61
|
+
Test::Unit::AutoRunner.run(true, test_dir)
|