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/Rakefile CHANGED
@@ -2,7 +2,7 @@
2
2
  #
3
3
  # Rakefile - This file is part of the RubyTree package.
4
4
  #
5
- # Copyright (c) 2006-2015 Anupam Sengupta
5
+ # Copyright (c) 2006-2022 Anupam Sengupta
6
6
  #
7
7
  # All rights reserved.
8
8
  #
@@ -31,49 +31,54 @@
31
31
  # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32
32
  # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
33
  #
34
+ #
35
+ # frozen_string_literal: true
34
36
 
35
37
  require 'rubygems'
36
- GEM_SPEC = eval(File.read("rubytree.gemspec")) # Load the gemspec.
38
+
39
+ # @todo: Check if Bundler needs to be `require`d.
40
+ GEM_SPEC = Bundler.load_gemspec(File.join(__dir__, 'rubytree.gemspec'))
37
41
 
38
42
  PKG_NAME = GEM_SPEC.name
39
43
  PKG_VER = GEM_SPEC.version
40
44
  GEM_NAME = "#{PKG_NAME}-#{PKG_VER}.gem"
41
45
 
42
- desc "Default Task (Run the tests)"
46
+ desc 'Default Task (Run the tests)'
43
47
  task :default do
44
- if ENV["COVERAGE"]
45
- Rake::Task["test:coverage"].invoke
48
+ if ENV['COVERAGE']
49
+ Rake::Task['test:coverage'].invoke
46
50
  else
47
- Rake::Task["test:unit"].invoke
48
- Rake::Task["spec"].invoke
51
+ Rake::Task['test:unit'].invoke
52
+ Rake::Task['spec'].invoke
49
53
  end
50
54
  end
51
55
 
52
- desc "Display the current gem version"
56
+ desc 'Display the current gem version'
53
57
  task :version do
54
58
  puts "Current Version: #{GEM_NAME}"
55
59
  end
56
60
 
57
61
  require 'rake/clean'
58
- task :clean => 'gem:clobber_package'
62
+ desc 'Remove all generated files.'
63
+ task clean: 'gem:clobber_package'
59
64
  CLEAN.include('coverage')
60
- task :clobber => [:clean, 'doc:clobber_rdoc', 'doc:clobber_yard']
65
+ task clobber: [:clean, 'doc:clobber_rdoc', 'doc:clobber_yard']
61
66
 
62
- desc "Open an irb session preloaded with this library"
67
+ desc 'Open an irb session preloaded with this library'
63
68
  task :console do
64
- sh "irb -rubygems -r ./lib/tree.rb"
69
+ sh 'irb -rubygems -r ./lib/tree.rb'
65
70
  end
66
71
 
67
- namespace :doc do # ................................ Documentation
72
+ namespace :doc do # ................................ Documentation
68
73
  begin
69
- gem 'rdoc', ">= 2.4.2" # To get around a stupid bug in Ruby 1.9.2 Rake.
74
+ gem 'rdoc', '>= 6.4.0' # To get around a stupid bug in Ruby 1.9.2 Rake.
70
75
  require 'rdoc/task'
71
76
  Rake::RDocTask.new do |rdoc|
72
77
  rdoc.rdoc_dir = 'rdoc'
73
- rdoc.title = "#{PKG_NAME}-#{PKG_VER}"
74
- rdoc.main = 'README.rdoc'
78
+ rdoc.title = "RubyTree Documenation: #{PKG_NAME}-#{PKG_VER}"
79
+ rdoc.main = 'README.md'
75
80
  rdoc.rdoc_files.include(GEM_SPEC.extra_rdoc_files)
76
- rdoc.rdoc_files.include('lib/**/*.rb')
81
+ rdoc.rdoc_files.include('./lib/**/*.rb')
77
82
  end
78
83
  rescue LoadError
79
84
  # Oh well.
@@ -83,22 +88,25 @@ namespace :doc do # ................................ Documentation
83
88
  require 'yard'
84
89
  YARD::Rake::YardocTask.new do |t|
85
90
  t.files = ['lib/**/*.rb', '-', GEM_SPEC.extra_rdoc_files]
86
- t.options = ['--no-private', '--embed-mixins']
91
+ t.options = %w[--no-private --embed-mixins]
87
92
  end
88
93
  rescue LoadError
89
94
  # Oh well.
90
95
  end
91
96
 
92
- desc "Remove YARD Documentation"
97
+ desc 'Remove YARD Documentation'
93
98
  task :clobber_yard do
94
99
  rm_rf 'doc'
95
100
  end
96
101
  end
97
102
 
98
- desc "Run the test cases"
99
- task :test => 'test:unit'
103
+ desc 'Run the unit tests'
104
+ task test: %w[test:unit]
100
105
 
101
- namespace :test do # ................................ Test related
106
+ # ................................ Test related
107
+ namespace :test do
108
+ desc 'Run all the tests'
109
+ task all: %w[test:unit test:spec test:examples]
102
110
 
103
111
  require 'rake/testtask'
104
112
  Rake::TestTask.new(:unit) do |test|
@@ -107,7 +115,19 @@ namespace :test do # ................................ Test related
107
115
  test.verbose = false
108
116
  end
109
117
 
110
- desc "Run the examples"
118
+ # ................................ rspec tests
119
+ begin
120
+ require 'rspec/core/rake_task'
121
+
122
+ RSpec::Core::RakeTask.new(:spec) do |t|
123
+ t.fail_on_error = false
124
+ t.rspec_opts = ['--color', '--format doc']
125
+ end
126
+ rescue LoadError
127
+ # Cannot load rspec.
128
+ end
129
+
130
+ desc 'Run the examples'
111
131
  Rake::TestTask.new(:examples) do |example|
112
132
  example.libs << 'lib' << 'examples'
113
133
  example.pattern = 'examples/**/example_*.rb'
@@ -115,7 +135,7 @@ namespace :test do # ................................ Test related
115
135
  example.warning = false
116
136
  end
117
137
 
118
- desc "Run the code coverage"
138
+ desc 'Run the code coverage'
119
139
  task :coverage do
120
140
  ruby 'test/run_test.rb'
121
141
  end
@@ -123,7 +143,7 @@ namespace :test do # ................................ Test related
123
143
  begin
124
144
  require 'rcov/rcovtask'
125
145
  Rcov::RcovTask.new(:rcov) do |t|
126
- t.libs << "test"
146
+ t.libs << 'test'
127
147
  t.test_files = FileList['test/**/test_*.rb']
128
148
  t.verbose = true
129
149
  t.rcov_opts << '--exclude /gems/,/Library/,/usr/,spec,lib/tasks'
@@ -131,41 +151,38 @@ namespace :test do # ................................ Test related
131
151
  rescue LoadError
132
152
  # Oh well. Can't have everything.
133
153
  end
134
-
135
154
  end
136
155
 
137
- begin # ................................ rspec tests
138
- require 'rspec/core/rake_task'
139
-
140
- RSpec::Core::RakeTask.new(:spec) do |t|
141
- t.fail_on_error = false
142
- t.rspec_opts = ["--color", "--format doc"]
156
+ # ................................ Emacs Tags
157
+ namespace :tag do
158
+ require 'rtagstask'
159
+ RTagsTask.new(:tags) do |rd|
160
+ rd.vi = false
161
+ CLEAN.include('TAGS')
143
162
  end
144
163
  rescue LoadError
145
- # Cannot load rspec.
164
+ # Oh well. Can't have everything.
146
165
  end
147
166
 
148
- namespace :tag do # ................................ Emacs Tags
149
- begin
150
- require 'rtagstask'
151
- RTagsTask.new(:tags) do |rd|
152
- rd.vi = false
153
- CLEAN.include('TAGS')
154
- end
155
- rescue LoadError
156
- # Oh well. Can't have everything.
157
- end
158
- end
159
-
160
- namespace :gem do # ................................ Gem related
167
+ # ................................ Gem related
168
+ namespace :gem do
161
169
  require 'rubygems/package_task'
162
170
  Gem::PackageTask.new(GEM_SPEC) do |pkg|
163
171
  pkg.need_zip = true
164
172
  pkg.need_tar = true
165
173
  end
166
174
 
167
- desc "Push the gem into the Rubygems repository"
168
- task :push => :gem do
175
+ desc 'Push the gem into the Rubygems repository'
176
+ task push: :gem do
169
177
  sh "gem push pkg/#{GEM_NAME}"
170
178
  end
171
179
  end
180
+
181
+ # ................................ Ruby linting
182
+ require 'rubocop/rake_task'
183
+
184
+ RuboCop::RakeTask.new(:rubocop) do |t|
185
+ t.options = ['--display-cop-names']
186
+ t.requires << 'rubocop-rake'
187
+ t.requires << 'rubocop-rspec'
188
+ end
data/TODO.org CHANGED
@@ -183,10 +183,7 @@
183
183
  This proposed change does make sense at one level (since the root node does not have any parent), but returning root
184
184
  as root's root (no pun intended) makes accessing the root from anywhere in the tree much easier.
185
185
 
186
-
187
-
188
-
189
- * R0.9.5
186
+ * R0.9.5 :ARCHIVE:
190
187
  ** DONE Add the `#get_path_as_string` method from feature request #48 :ARCHIVE:
191
188
  CLOSED: [2015-05-30 Sat 15:55]
192
189
  ** DONE Fix [[Issue:32][Issue #32]] and enable move semantics on the TreeNode#add method. :ARCHIVE:
@@ -202,11 +199,20 @@
202
199
  CLOSED: [2014-11-01 Sat 20:11]
203
200
 
204
201
 
202
+ * R2.0.0
203
+
204
+ This is primarily a *modernization* of the library, with removal of deprecated methods, the much-hated dependency on
205
+ ~structured_warnings~, and cleanup of other cruft.
206
+
207
+ In addition, the CI pipeline has been moved from <https://travis.ci> to ~Github Actions~.
205
208
 
209
+ - [X] Merge the modernization PR from @jmortlock (multiple changes).
210
+ - [X] Update the documentation to reflect the modernization changes.
206
211
 
207
- * Next Release
208
- DEADLINE: <2014-12-01 Mon>
209
- ** STARTED [#A] Resolve the infinite loop bug if a node is added to itself as a child :Partial:
212
+
213
+ * Unplanned / Not assigned to any release
214
+ *** STARTED Convert all documentation to markdown mode.
215
+ *** STARTED [#A] Resolve the infinite loop bug if a node is added to itself as a child :Partial:
210
216
  [[Issue:5][Issue #5.]]
211
217
 
212
218
  This is a subtle problem to resolve. The specific case of a node
@@ -237,15 +243,8 @@
237
243
  duplicates). This needs to be a hash (to allow O(1) access),
238
244
  and will sacrifice memory. There might be a need to
239
245
  restructure the internals to make better use of memory.
240
- ** STARTED Convert all documentation to markdown mode.
241
- ** TODO Expand the examples section, and add supporting documentation
246
+ *** TODO Expand the examples section, and add supporting documentation
242
247
 
243
- * Unplanned / Not assigned to any release
244
- *** DONE [#A] Migrate the website and references from http://rubyforge.org/ :ARCHIVE:
245
- CLOSED: [2014-07-04 Fri 22:18]
246
- *** DONE Revert the forced install of rubygem 2.1.11 from [[file:.travis.yml][.travis.yml]] :ARCHIVE:
247
- CLOSED: [2014-01-12 Sun 19:06]
248
- The issue seems to have been resolved with the 2.2.1 release of Rubygems.
249
248
  *** TODO Create a cycle-detection/validation mechanism to prevent cyclic graphs of nodes.
250
249
  *** TODO Create a generic validation method to check for various issues in the created tree.
251
250
  *** TODO Add a FAQ document to the project.
@@ -258,6 +257,11 @@
258
257
  *** TODO Add a YAML export method to the TreeNode class.
259
258
 
260
259
  *** TODO marshal_load method probably should be a class method. It currently clobbers self.
260
+ *** DONE Revert the forced install of rubygem 2.1.11 from [[file:.travis.yml][.travis.yml]] :ARCHIVE:
261
+ CLOSED: [2014-01-12 Sun 19:06]
262
+ The issue seems to have been resolved with the 2.2.1 release of Rubygems.
263
+ *** DONE [#A] Migrate the website and references from http://rubyforge.org/ :ARCHIVE:
264
+ CLOSED: [2014-07-04 Fri 22:18]
261
265
  *** DONE Fix bug # [[http://rubyforge.org/tracker/index.php%3Ffunc%3Ddetail&aid%3D22535&group_id%3D1215&atid%3D4793][22535]]: The method Tree::TreeNode#depth is a misnomer. The current definition actually provides the height function. :ARCHIVE:
262
266
  DEADLINE: <2010-01-09 Sat> CLOSED: [2010-01-03 Sun 22:15]
263
267
 
@@ -3,8 +3,8 @@
3
3
  # example_basic.rb:: Basic usage of the tree library.
4
4
  #
5
5
  # Author: Anupam Sengupta
6
- # Time-stamp: <2015-12-31 22:17:30 anupam>
7
- # Copyright (C) 2013, 2015 Anupam Sengupta <anupamsg@gmail.com>
6
+ # Time-stamp: <2022-06-19 22:52:29 anupam>
7
+ # Copyright (C) 2013, 2015, 2022 Anupam Sengupta <anupamsg@gmail.com>
8
8
  #
9
9
  # The following example implements this tree structure:
10
10
  #
@@ -21,24 +21,31 @@
21
21
  # +-------+-------+
22
22
  # | GRANDCHILD 1 |
23
23
  # +---------------+
24
+ #
25
+ # frozen_string_literal: true
24
26
 
25
27
  # ..... Example starts.
26
- require 'tree' # Load the library
28
+ require 'tree' # Load the library
27
29
 
28
- # ..... Create the root node first. Note that every node has a name and an optional content payload.
29
- root_node = Tree::TreeNode.new("ROOT", "Root Content")
30
+ # ..... Create the root node first. Note that every node has a name and an
31
+ # ..... optional content payload.
32
+ root_node = Tree::TreeNode.new('ROOT', 'Root Content')
30
33
  root_node.print_tree
31
34
 
32
- # ..... Now insert the child nodes. Note that you can "chain" the child insertions for a given path to any depth.
33
- root_node << Tree::TreeNode.new("CHILD1", "Child1 Content") << Tree::TreeNode.new("GRANDCHILD1", "GrandChild1 Content")
34
- root_node << Tree::TreeNode.new("CHILD2", "Child2 Content")
35
+ # ..... Now insert the child nodes. Note that you can "chain" the child
36
+ # ..... insertions for a given path to any depth.
37
+ root_node << Tree::TreeNode.new('CHILD1', 'Child1 Content') \
38
+ << Tree::TreeNode.new('GRANDCHILD1', 'GrandChild1 Content')
39
+ root_node << Tree::TreeNode.new('CHILD2', 'Child2 Content')
35
40
 
36
- # ..... Lets print the representation to stdout. This is primarily used for debugging purposes.
41
+ # ..... Lets print the representation to stdout. This is primarily used for
42
+ # ..... debugging purposes.
37
43
  root_node.print_tree
38
44
 
39
- # ..... Lets directly access children and grandchildren of the root. The can be "chained" for a given path to any depth.
40
- child1 = root_node["CHILD1"]
41
- grand_child1 = root_node["CHILD1"]["GRANDCHILD1"]
45
+ # ..... Lets directly access children and grandchildren of the root. The can be
46
+ # ..... "chained" for a given path to any depth.
47
+ child1 = root_node['CHILD1']
48
+ grand_child1 = root_node['CHILD1']['GRANDCHILD1']
42
49
 
43
50
  # ..... Now lets retrieve siblings of the current node as an array.
44
51
  siblings_of_child1 = child1.siblings
data/lib/rubytree.rb CHANGED
@@ -8,9 +8,7 @@
8
8
  #
9
9
  # Author:: Anupam Sengupta (anupamsg@gmail.com)
10
10
  #
11
- # Copyright (c) 2012, 2015 Anupam Sengupta
12
- #
13
- # All rights reserved.
11
+ # Copyright (c) 2012-2022 Anupam Sengupta. All rights reserved.
14
12
  #
15
13
  # Redistribution and use in source and binary forms, with or without
16
14
  # modification, are permitted provided that the following conditions are met:
@@ -37,5 +35,6 @@
37
35
  # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38
36
  # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39
37
  #
38
+ # frozen_string_literal: true
40
39
 
41
- require "tree.rb"
40
+ require 'tree'
@@ -8,9 +8,7 @@
8
8
  # Author:: Anupam Sengupta (anupamsg@gmail.com)
9
9
  #
10
10
 
11
- # Copyright (c) 2007, 2008, 2009, 2010, 2012, 2013, 2014, 2015 Anupam Sengupta
12
- #
13
- # All rights reserved.
11
+ # Copyright (c) 2007-2022 Anupam Sengupta. All rights reserved.
14
12
  #
15
13
  # Redistribution and use in source and binary forms, with or without
16
14
  # modification, are permitted provided that the following conditions are met:
@@ -37,11 +35,11 @@
37
35
  # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38
36
  # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39
37
  #
38
+ # frozen_string_literal: true
40
39
 
41
- require 'tree'
40
+ require_relative '../tree'
42
41
 
43
42
  module Tree
44
-
45
43
  # Provides a Binary tree implementation. This node allows only two child nodes
46
44
  # (left and right child). It also provides direct access to the left or right
47
45
  # child, including assignment to the same.
@@ -51,7 +49,6 @@ module Tree
51
49
  # @author Anupam Sengupta
52
50
  #
53
51
  class BinaryTreeNode < TreeNode
54
-
55
52
  # @!group Core Attributes
56
53
 
57
54
  # @!attribute [rw] left_child
@@ -78,26 +75,32 @@ module Tree
78
75
  children[1]
79
76
  end
80
77
 
81
- # @!attribute is_left_child?
78
+ # @!attribute left_child?
82
79
  # +true+ if the receiver node is the left child of its parent.
83
80
  # Always returns +false+ if it is a root node.
84
81
  #
85
82
  # @return [Boolean] +true+ if this is the left child of its parent.
86
- def is_left_child?
87
- return false if is_root?
83
+ def left_child?
84
+ return false if root?
85
+
88
86
  self == parent.left_child
89
87
  end
90
88
 
91
- # @!attribute [r] is_right_child?
89
+ alias is_left_child? left_child? # @todo: Aliased for eventual replacement
90
+
91
+ # @!attribute [r] right_child?
92
92
  # +true+ if the receiver node is the right child of its parent.
93
93
  # Always returns +false+ if it is a root node.
94
94
  #
95
95
  # @return [Boolean] +true+ if this is the right child of its parent.
96
- def is_right_child?
97
- return false if is_root?
96
+ def right_child?
97
+ return false if root?
98
+
98
99
  self == parent.right_child
99
100
  end
100
101
 
102
+ alias is_right_child? right_child? # @todo: Aliased for eventual replacement
103
+
101
104
  # @!group Structure Modification
102
105
 
103
106
  # Adds the specified child node to the receiver node. The child node's
@@ -114,12 +117,11 @@ module Tree
114
117
  # @raise [ArgumentError] This exception is raised if two children are
115
118
  # already present.
116
119
  def add(child)
117
- raise ArgumentError, "Already has two child nodes" if @children.size == 2
120
+ raise ArgumentError, 'Already has two child nodes' if @children.size == 2
118
121
 
119
122
  super(child)
120
123
  end
121
124
 
122
-
123
125
  # Instantiate and insert child nodes from data in a Ruby +Hash+
124
126
  #
125
127
  # This method is used in conjunction with {Tree::TreeNode.from_hash} to
@@ -150,12 +152,13 @@ module Tree
150
152
  # @raise [ArgumentError] This exception is raised if a non-hash is passed.
151
153
  # @return [Array] Array of child nodes added
152
154
  def add_from_hash(hashed_subtree)
153
- raise ArgumentError, "Too many children"\
155
+ raise ArgumentError, 'Too many children'\
154
156
  if hashed_subtree.size + @children.size > 2
157
+
155
158
  super(hashed_subtree)
156
159
  end
157
160
 
158
- # Performs inorder traversal (including this node).
161
+ # Performs in-order traversal (including this node).
159
162
  #
160
163
  # @yieldparam node [Tree::BinaryTreeNode] Each node (in-order).
161
164
  #
@@ -167,26 +170,25 @@ module Tree
167
170
  # @see #each
168
171
  # @see #preordered_each
169
172
  # @see #postordered_each
170
- def inordered_each(&block)
171
-
172
- return self.to_enum unless block_given?
173
+ # noinspection RubyUnusedLocalVariable
174
+ def inordered_each
175
+ return to_enum unless block_given?
173
176
 
174
177
  node_stack = []
175
178
  current_node = self
176
179
 
177
- until node_stack.empty? and current_node == nil
180
+ until node_stack.empty? && current_node.nil?
178
181
  if current_node
179
182
  node_stack.push(current_node)
180
183
  current_node = current_node.left_child
181
184
  else
182
- current_node = node_stack.pop()
185
+ current_node = node_stack.pop
183
186
  yield current_node
184
187
  current_node = current_node.right_child
185
188
  end
186
189
  end
187
190
 
188
- return self if block_given?
189
-
191
+ self if block_given?
190
192
  end
191
193
 
192
194
  # A protected method to allow insertion of child nodes at the specified
@@ -201,7 +203,7 @@ module Tree
201
203
  #
202
204
  # @raise [ArgumentError] If the index is out of limits.
203
205
  def set_child_at(child, at_index)
204
- raise ArgumentError "A binary tree cannot have more than two children."\
206
+ raise ArgumentError 'A binary tree cannot have more than two children.'\
205
207
  unless (0..1).include? at_index
206
208
 
207
209
  @children[at_index] = child
@@ -242,9 +244,7 @@ module Tree
242
244
 
243
245
  # Swaps the left and right child nodes of the receiver node with each other.
244
246
  def swap_children
245
- self.left_child, self.right_child = self.right_child, self.left_child
247
+ self.left_child, self.right_child = right_child, left_child
246
248
  end
247
-
248
249
  end
249
-
250
250
  end
@@ -2,14 +2,12 @@
2
2
  #
3
3
  # = rubytree_deps.rb - Dependencies for RubyTree
4
4
  #
5
- # Centralizes and lists the dependencies forthe RubyTree gem.
5
+ # Centralizes and lists the dependencies for the RubyTree gem.
6
6
  #
7
7
  # Author:: Anupam Sengupta (anupamsg@gmail.com)
8
8
  #
9
9
 
10
- # Copyright (c) 2006-2015 Anupam Sengupta
11
- #
12
- # All rights reserved.
10
+ # Copyright (c) 2006-2022 Anupam Sengupta. All rights reserved.
13
11
  #
14
12
  # Redistribution and use in source and binary forms, with or without
15
13
  # modification, are permitted provided that the following conditions are met:
@@ -36,14 +34,13 @@
36
34
  # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37
35
  # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38
36
  #
37
+ # frozen_string_literal: true
39
38
 
40
- require 'structured_warnings'
41
39
  require 'json'
42
40
 
43
- require 'tree/version'
44
- require 'tree/utils/metrics_methods'
45
- require 'tree/utils/path_methods'
46
- require 'tree/utils/camel_case_method_handler'
47
- require 'tree/utils/json_converter'
48
- require 'tree/utils/tree_merge_handler'
49
- require 'tree/utils/hash_converter'
41
+ require_relative '../tree/version'
42
+ require_relative '../tree/utils/metrics_methods'
43
+ require_relative '../tree/utils/path_methods'
44
+ require_relative '../tree/utils/json_converter'
45
+ require_relative '../tree/utils/tree_merge_handler'
46
+ require_relative '../tree/utils/hash_converter'