rubytree 1.0.2 → 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 +4 -4
- data/API-CHANGES.md +153 -0
- data/Gemfile +2 -6
- data/Gemfile.lock +40 -55
- data/History.md +410 -0
- data/LICENSE.md +1 -1
- data/README.md +21 -24
- data/Rakefile +41 -20
- data/TODO.org +19 -15
- data/examples/example_basic.rb +14 -7
- data/lib/rubytree.rb +2 -3
- data/lib/tree/binarytree.rb +13 -12
- data/lib/tree/tree_deps.rb +2 -5
- data/lib/tree/utils/hash_converter.rb +129 -121
- data/lib/tree/utils/json_converter.rb +80 -77
- data/lib/tree/utils/metrics_methods.rb +14 -47
- data/lib/tree/utils/path_methods.rb +11 -11
- data/lib/tree/utils/tree_merge_handler.rb +80 -80
- data/lib/tree/utils/utils.rb +9 -7
- data/lib/tree/version.rb +3 -4
- data/lib/tree.rb +80 -82
- data/rubytree.gemspec +61 -38
- data/spec/spec_helper.rb +4 -2
- data/spec/tree_spec.rb +129 -28
- data/test/run_test.rb +4 -3
- data/test/test_binarytree.rb +25 -45
- data/test/test_rubytree_require.rb +2 -1
- data/test/test_subclassed_node.rb +2 -20
- data/test/test_thread_and_fiber.rb +4 -4
- data/test/test_tree.rb +126 -199
- metadata +103 -69
- data/API-CHANGES.rdoc +0 -99
- data/History.rdoc +0 -303
- data/lib/tree/utils/camel_case_method_handler.rb +0 -77
- data/setup.rb +0 -1565
data/lib/tree.rb
CHANGED
@@ -9,9 +9,7 @@
|
|
9
9
|
# Author:: Anupam Sengupta (anupamsg@gmail.com)
|
10
10
|
#
|
11
11
|
|
12
|
-
# Copyright (c) 2006-
|
13
|
-
#
|
14
|
-
# All rights reserved.
|
12
|
+
# Copyright (c) 2006-2022 Anupam Sengupta. All rights reserved.
|
15
13
|
#
|
16
14
|
# Redistribution and use in source and binary forms, with or without
|
17
15
|
# modification, are permitted provided that the following conditions are met:
|
@@ -38,6 +36,7 @@
|
|
38
36
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
39
37
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
40
38
|
#
|
39
|
+
# frozen_string_literal: true
|
41
40
|
|
42
41
|
require 'tree/tree_deps'
|
43
42
|
|
@@ -88,7 +87,6 @@ module Tree
|
|
88
87
|
include Comparable
|
89
88
|
include Tree::Utils::TreeMetricsHandler
|
90
89
|
include Tree::Utils::TreePathHandler
|
91
|
-
include Tree::Utils::CamelCaseMethodHandler
|
92
90
|
include Tree::Utils::JSONConverter
|
93
91
|
include Tree::Utils::TreeMergeHandler
|
94
92
|
include Tree::Utils::HashConverter
|
@@ -132,38 +130,44 @@ module Tree
|
|
132
130
|
# @return [Tree::TreeNode] Root of the (sub)tree.
|
133
131
|
def root
|
134
132
|
root = self
|
135
|
-
root = root.parent until root.
|
133
|
+
root = root.parent until root.root?
|
136
134
|
root
|
137
135
|
end
|
138
136
|
|
139
|
-
# @!attribute [r]
|
137
|
+
# @!attribute [r] root?
|
140
138
|
# Returns +true+ if this is a root node. Note that
|
141
139
|
# orphaned children will also be reported as root nodes.
|
142
140
|
#
|
143
141
|
# @return [Boolean] +true+ if this is a root node.
|
144
|
-
def
|
142
|
+
def root?
|
145
143
|
@parent.nil?
|
146
144
|
end
|
147
145
|
|
148
|
-
#
|
146
|
+
alias is_root? root? # @todo: Aliased for eventual replacement
|
147
|
+
|
148
|
+
# @!attribute [r] content?
|
149
149
|
# +true+ if this node has content.
|
150
150
|
#
|
151
151
|
# @return [Boolean] +true+ if the node has content.
|
152
|
-
def
|
152
|
+
def content?
|
153
153
|
@content != nil
|
154
154
|
end
|
155
155
|
|
156
|
-
#
|
156
|
+
alias has_content? content? # @todo: Aliased for eventual replacement
|
157
|
+
|
158
|
+
# @!attribute [r] leaf?
|
157
159
|
# +true+ if this node is a _leaf_ - i.e., one without
|
158
160
|
# any children.
|
159
161
|
#
|
160
162
|
# @return [Boolean] +true+ if this is a leaf node.
|
161
163
|
#
|
162
|
-
# @see #
|
163
|
-
def
|
164
|
-
!
|
164
|
+
# @see #children?
|
165
|
+
def leaf?
|
166
|
+
!children?
|
165
167
|
end
|
166
168
|
|
169
|
+
alias is_leaf? leaf? # @todo: Aliased for eventual replacement
|
170
|
+
|
167
171
|
# @!attribute [r] parentage
|
168
172
|
# An array of ancestors of this node in reversed order
|
169
173
|
# (the first element is the immediate parent of this node).
|
@@ -173,7 +177,7 @@ module Tree
|
|
173
177
|
# @return [Array<Tree::TreeNode>] An array of ancestors of this node
|
174
178
|
# @return [nil] if this is a root node.
|
175
179
|
def parentage
|
176
|
-
return nil if
|
180
|
+
return nil if root?
|
177
181
|
|
178
182
|
parentage_array = []
|
179
183
|
prev_parent = parent
|
@@ -184,16 +188,18 @@ module Tree
|
|
184
188
|
parentage_array
|
185
189
|
end
|
186
190
|
|
187
|
-
# @!attribute [r]
|
191
|
+
# @!attribute [r] children?
|
188
192
|
# +true+ if the this node has any child node.
|
189
193
|
#
|
190
194
|
# @return [Boolean] +true+ if child nodes exist.
|
191
195
|
#
|
192
|
-
# @see #
|
193
|
-
def
|
194
|
-
|
196
|
+
# @see #leaf?
|
197
|
+
def children?
|
198
|
+
!@children.empty?
|
195
199
|
end
|
196
200
|
|
201
|
+
alias has_children? children? # @todo: Aliased for eventual replacement
|
202
|
+
|
197
203
|
# @!group Node Creation
|
198
204
|
|
199
205
|
# Creates a new node with a name and optional content.
|
@@ -217,16 +223,10 @@ module Tree
|
|
217
223
|
def initialize(name, content = nil)
|
218
224
|
raise ArgumentError, 'Node name HAS to be provided!' if name.nil?
|
219
225
|
|
226
|
+
name = name.to_s if name.is_a?(Integer)
|
220
227
|
@name = name
|
221
228
|
@content = content
|
222
229
|
|
223
|
-
if name.is_a?(Integer)
|
224
|
-
warn StructuredWarnings::StandardWarning,
|
225
|
-
'Using integer as node name.'\
|
226
|
-
' Semantics of TreeNode[] may not be what you expect!'\
|
227
|
-
" #{name} #{content}"
|
228
|
-
end
|
229
|
-
|
230
230
|
set_as_root!
|
231
231
|
@children_hash = {}
|
232
232
|
@children = []
|
@@ -237,7 +237,13 @@ module Tree
|
|
237
237
|
#
|
238
238
|
# @return [Tree::TreeNode] A copy of this node.
|
239
239
|
def detached_copy
|
240
|
-
|
240
|
+
cloned_content =
|
241
|
+
begin
|
242
|
+
@content&.clone
|
243
|
+
rescue TypeError
|
244
|
+
@content
|
245
|
+
end
|
246
|
+
self.class.new(@name, cloned_content)
|
241
247
|
end
|
242
248
|
|
243
249
|
# Returns a copy of entire (sub-)tree from this node.
|
@@ -261,14 +267,14 @@ module Tree
|
|
261
267
|
# representation of the (sub)tree rooted at this node.
|
262
268
|
#
|
263
269
|
def marshal_dump
|
264
|
-
collect
|
270
|
+
collect(&:create_dump_rep)
|
265
271
|
end
|
266
272
|
|
267
273
|
# Creates a dump representation of this node and returns the same as
|
268
274
|
# a hash.
|
269
275
|
def create_dump_rep # :nodoc:
|
270
276
|
{ name: @name,
|
271
|
-
parent: (
|
277
|
+
parent: (root? ? nil : @parent.name),
|
272
278
|
content: Marshal.dump(@content) }
|
273
279
|
end
|
274
280
|
|
@@ -279,6 +285,9 @@ module Tree
|
|
279
285
|
# {Marshal}[http://ruby-doc.org/core-1.8.7/Marshal.html] class for
|
280
286
|
# additional details.
|
281
287
|
#
|
288
|
+
# NOTE: This is a potentially *unsafe* method with similar concerns as with
|
289
|
+
# the Marshal#load method, and should *not* be used with untrusted user
|
290
|
+
# provided data.
|
282
291
|
#
|
283
292
|
# @todo This method probably should be a class method. It currently clobbers
|
284
293
|
# self and makes itself the root.
|
@@ -291,7 +300,7 @@ module Tree
|
|
291
300
|
content = Marshal.load(node_hash[:content])
|
292
301
|
|
293
302
|
if parent_name
|
294
|
-
nodes[name] = current_node =
|
303
|
+
nodes[name] = current_node = self.class.new(name, content)
|
295
304
|
nodes[parent_name].add current_node
|
296
305
|
else
|
297
306
|
# This is the root node, hence initialize self.
|
@@ -309,7 +318,9 @@ module Tree
|
|
309
318
|
#
|
310
319
|
# @return [String] A string representation of the node.
|
311
320
|
def to_s
|
312
|
-
"Node Name: #{@name} Content: #{@content.to_s || '<Empty>'}
|
321
|
+
"Node Name: #{@name} Content: #{@content.to_s || '<Empty>'} " \
|
322
|
+
"Parent: #{root? ? '<None>' : @parent.name.to_s} " \
|
323
|
+
"Children: #{@children.length} Total Nodes: #{size}"
|
313
324
|
end
|
314
325
|
|
315
326
|
# @!group Structure Modification
|
@@ -422,7 +433,7 @@ module Tree
|
|
422
433
|
def rename(new_name)
|
423
434
|
old_name = @name
|
424
435
|
|
425
|
-
if
|
436
|
+
if root?
|
426
437
|
self.name = new_name
|
427
438
|
else
|
428
439
|
@parent.rename_child old_name, new_name
|
@@ -516,7 +527,7 @@ module Tree
|
|
516
527
|
#
|
517
528
|
# @see #remove_all!
|
518
529
|
def remove_from_parent!
|
519
|
-
@parent.remove!(self) unless
|
530
|
+
@parent.remove!(self) unless root?
|
520
531
|
end
|
521
532
|
|
522
533
|
# Removes all children from this node. If an independent reference exists to
|
@@ -528,7 +539,7 @@ module Tree
|
|
528
539
|
# @see #remove!
|
529
540
|
# @see #remove_from_parent!
|
530
541
|
def remove_all!
|
531
|
-
@children.each
|
542
|
+
@children.each(&:remove_all!)
|
532
543
|
|
533
544
|
@children_hash.clear
|
534
545
|
@children.clear
|
@@ -549,7 +560,7 @@ module Tree
|
|
549
560
|
# The nodes become immutable after this operation. In effect, the entire tree's
|
550
561
|
# structure and contents become _read-only_ and cannot be changed.
|
551
562
|
def freeze_tree!
|
552
|
-
each
|
563
|
+
each(&:freeze)
|
553
564
|
end
|
554
565
|
|
555
566
|
# @!endgroup
|
@@ -560,45 +571,31 @@ module Tree
|
|
560
571
|
#
|
561
572
|
# - If the +name+ argument is an _Integer_, then the in-sequence
|
562
573
|
# array of children is accessed using the argument as the
|
563
|
-
# *index* (zero-based).
|
564
|
-
# +num_as_name+ argument is +true+, then the +name+ is used
|
565
|
-
# literally as a name, and *NOT* as an *index*
|
574
|
+
# *index* (zero-based).
|
566
575
|
#
|
567
576
|
# - If the +name+ argument is *NOT* an _Integer_, then it is taken to
|
568
577
|
# be the *name* of the child node to be returned.
|
569
578
|
#
|
570
|
-
#
|
571
|
-
#
|
572
|
-
# redundant use of the +num_as_name+ flag.)
|
579
|
+
# - To use an _Integer_ as the name, convert it to a _String_ first using
|
580
|
+
# +<integer>.to_s+.
|
573
581
|
#
|
574
582
|
# @param [String|Number] name_or_index Name of the child, or its
|
575
583
|
# positional index in the array of child nodes.
|
576
584
|
#
|
577
|
-
# @param [Boolean] num_as_name Whether to treat the +Integer+
|
578
|
-
# +name+ argument as an actual name, and *NOT* as an _index_ to
|
579
|
-
# the children array.
|
580
|
-
#
|
581
585
|
# @return [Tree::TreeNode] the requested child node. If the index
|
582
586
|
# in not in range, or the name is not present, then a +nil+
|
583
587
|
# is returned.
|
584
588
|
#
|
585
|
-
# @note The use of +Integer+ names is allowed by using the optional
|
586
|
-
# +num_as_name+ flag.
|
587
|
-
#
|
588
589
|
# @raise [ArgumentError] Raised if the +name_or_index+ argument is +nil+.
|
589
590
|
#
|
590
591
|
# @see #add
|
591
592
|
# @see #initialize
|
592
|
-
def [](name_or_index
|
593
|
+
def [](name_or_index)
|
593
594
|
raise ArgumentError, 'Name_or_index needs to be provided!' if name_or_index.nil?
|
594
595
|
|
595
|
-
if name_or_index.is_a?(Integer)
|
596
|
+
if name_or_index.is_a?(Integer)
|
596
597
|
@children[name_or_index]
|
597
598
|
else
|
598
|
-
if num_as_name && !name_or_index.is_a?(Integer)
|
599
|
-
warn StructuredWarnings::StandardWarning,
|
600
|
-
'Redundant use of the `num_as_name` flag for non-integer node name'
|
601
|
-
end
|
602
599
|
@children_hash[name_or_index]
|
603
600
|
end
|
604
601
|
end
|
@@ -609,7 +606,6 @@ module Tree
|
|
609
606
|
# The traversal is *depth-first* and from *left-to-right* in pre-ordered
|
610
607
|
# sequence.
|
611
608
|
#
|
612
|
-
# @param [Object] block
|
613
609
|
# @yieldparam node [Tree::TreeNode] Each node.
|
614
610
|
#
|
615
611
|
# @see #preordered_each
|
@@ -651,7 +647,6 @@ module Tree
|
|
651
647
|
|
652
648
|
# Traverses the (sub)tree rooted at this node in post-ordered sequence.
|
653
649
|
#
|
654
|
-
# @param [Object] block
|
655
650
|
# @yieldparam node [Tree::TreeNode] Each node.
|
656
651
|
#
|
657
652
|
# @see #preordered_each
|
@@ -670,7 +665,7 @@ module Tree
|
|
670
665
|
|
671
666
|
until node_stack.empty?
|
672
667
|
peek_node = node_stack[0]
|
673
|
-
if peek_node.node.
|
668
|
+
if peek_node.node.children? && !peek_node.visited
|
674
669
|
peek_node.visited = true
|
675
670
|
# Add the children to the stack. Use the marking structure.
|
676
671
|
marked_children =
|
@@ -689,7 +684,6 @@ module Tree
|
|
689
684
|
# traversal at a given level is from *left-to-right*. this node itself is
|
690
685
|
# the first node to be traversed.
|
691
686
|
#
|
692
|
-
# @param [Object] block
|
693
687
|
# @yieldparam node [Tree::TreeNode] Each node.
|
694
688
|
#
|
695
689
|
# @see #preordered_each
|
@@ -741,7 +735,6 @@ module Tree
|
|
741
735
|
# May yield this node as well if this is a leaf node.
|
742
736
|
# Leaf traversal is *depth-first* and *left-to-right*.
|
743
737
|
#
|
744
|
-
# @param [Object] block
|
745
738
|
# @yieldparam node [Tree::TreeNode] Each leaf node.
|
746
739
|
#
|
747
740
|
# @see #each
|
@@ -752,10 +745,10 @@ module Tree
|
|
752
745
|
# noinspection RubyUnusedLocalVariable
|
753
746
|
def each_leaf
|
754
747
|
if block_given?
|
755
|
-
each { |node| yield(node) if node.
|
748
|
+
each { |node| yield(node) if node.leaf? }
|
756
749
|
self
|
757
750
|
else
|
758
|
-
self.select
|
751
|
+
self.select(&:leaf?)
|
759
752
|
end
|
760
753
|
end
|
761
754
|
|
@@ -813,22 +806,24 @@ module Tree
|
|
813
806
|
#
|
814
807
|
# @return [Tree::TreeNode] The first sibling node.
|
815
808
|
#
|
816
|
-
# @see #
|
809
|
+
# @see #first_sibling?
|
817
810
|
# @see #last_sibling
|
818
811
|
def first_sibling
|
819
|
-
|
812
|
+
root? ? self : parent.children.first
|
820
813
|
end
|
821
814
|
|
822
815
|
# Returns +true+ if this node is the first sibling at its level.
|
823
816
|
#
|
824
817
|
# @return [Boolean] +true+ if this is the first sibling.
|
825
818
|
#
|
826
|
-
# @see #
|
819
|
+
# @see #last_sibling?
|
827
820
|
# @see #first_sibling
|
828
|
-
def
|
821
|
+
def first_sibling?
|
829
822
|
first_sibling == self
|
830
823
|
end
|
831
824
|
|
825
|
+
alias is_first_sibling? first_sibling? # @todo: Aliased for eventual replacement
|
826
|
+
|
832
827
|
# Last sibling of this node. If this is the root node, then returns
|
833
828
|
# itself.
|
834
829
|
#
|
@@ -839,22 +834,24 @@ module Tree
|
|
839
834
|
#
|
840
835
|
# @return [Tree::TreeNode] The last sibling node.
|
841
836
|
#
|
842
|
-
# @see #
|
837
|
+
# @see #last_sibling?
|
843
838
|
# @see #first_sibling
|
844
839
|
def last_sibling
|
845
|
-
|
840
|
+
root? ? self : parent.children.last
|
846
841
|
end
|
847
842
|
|
848
843
|
# Returns +true+ if this node is the last sibling at its level.
|
849
844
|
#
|
850
845
|
# @return [Boolean] +true+ if this is the last sibling.
|
851
846
|
#
|
852
|
-
# @see #
|
847
|
+
# @see #first_sibling?
|
853
848
|
# @see #last_sibling
|
854
|
-
def
|
849
|
+
def last_sibling?
|
855
850
|
last_sibling == self
|
856
851
|
end
|
857
852
|
|
853
|
+
alias is_last_sibling? last_sibling? # @todo: Aliased for eventual replacement
|
854
|
+
|
858
855
|
# An array of siblings for this node. This node is excluded.
|
859
856
|
#
|
860
857
|
# If a block is provided, yields each of the sibling nodes to the block.
|
@@ -874,7 +871,7 @@ module Tree
|
|
874
871
|
parent.children.each { |sibling| yield sibling if sibling != self }
|
875
872
|
self
|
876
873
|
else
|
877
|
-
return [] if
|
874
|
+
return [] if root?
|
878
875
|
|
879
876
|
siblings = []
|
880
877
|
parent.children do |my_sibling|
|
@@ -891,10 +888,12 @@ module Tree
|
|
891
888
|
# @return [Boolean] +true+ if this is the only child of its parent.
|
892
889
|
#
|
893
890
|
# @see #siblings
|
894
|
-
def
|
895
|
-
|
891
|
+
def only_child?
|
892
|
+
root? ? true : parent.children.size == 1
|
896
893
|
end
|
897
894
|
|
895
|
+
alias is_only_child? only_child? # @todo: Aliased for eventual replacement
|
896
|
+
|
898
897
|
# Next sibling for this node.
|
899
898
|
# The _next_ node is defined as the node to right of this node.
|
900
899
|
#
|
@@ -906,7 +905,7 @@ module Tree
|
|
906
905
|
# @see #previous_sibling
|
907
906
|
# @see #siblings
|
908
907
|
def next_sibling
|
909
|
-
return nil if
|
908
|
+
return nil if root?
|
910
909
|
|
911
910
|
idx = parent.children.index(self)
|
912
911
|
parent.children.at(idx + 1) if idx
|
@@ -923,10 +922,10 @@ module Tree
|
|
923
922
|
# @see #next_sibling
|
924
923
|
# @see #siblings
|
925
924
|
def previous_sibling
|
926
|
-
return nil if
|
925
|
+
return nil if root?
|
927
926
|
|
928
927
|
idx = parent.children.index(self)
|
929
|
-
parent.children.at(idx - 1) if idx
|
928
|
+
parent.children.at(idx - 1) if idx&.positive?
|
930
929
|
end
|
931
930
|
|
932
931
|
# @!endgroup
|
@@ -941,7 +940,7 @@ module Tree
|
|
941
940
|
# this node is a 'predecessor'. Returns 'nil' if the other
|
942
941
|
# object is not a 'Tree::TreeNode'.
|
943
942
|
def <=>(other)
|
944
|
-
return nil if other.nil? || other.
|
943
|
+
return nil if other.nil? || !other.is_a?(Tree::TreeNode)
|
945
944
|
|
946
945
|
name <=> other.name
|
947
946
|
end
|
@@ -956,16 +955,16 @@ module Tree
|
|
956
955
|
block = lambda { |node, prefix|
|
957
956
|
puts "#{prefix} #{node.name}"
|
958
957
|
})
|
959
|
-
prefix = ''
|
958
|
+
prefix = ''.dup # dup NEEDs to be invoked to make this mutable.
|
960
959
|
|
961
|
-
if
|
960
|
+
if root?
|
962
961
|
prefix << '*'
|
963
962
|
else
|
964
|
-
prefix << '|' unless parent.
|
963
|
+
prefix << '|' unless parent.last_sibling?
|
965
964
|
prefix << (' ' * (level - 1) * 4)
|
966
|
-
prefix << (
|
965
|
+
prefix << (last_sibling? ? '+' : '|')
|
967
966
|
prefix << '---'
|
968
|
-
prefix << (
|
967
|
+
prefix << (children? ? '+' : '>')
|
969
968
|
end
|
970
969
|
|
971
970
|
block.call(self, prefix)
|
@@ -975,8 +974,7 @@ module Tree
|
|
975
974
|
|
976
975
|
# Child might be 'nil'
|
977
976
|
children do |child|
|
978
|
-
child&.print_tree(level + 1,
|
979
|
-
max_depth, block)
|
977
|
+
child&.print_tree(level + 1, max_depth, block)
|
980
978
|
end
|
981
979
|
end
|
982
980
|
end
|
data/rubytree.gemspec
CHANGED
@@ -3,51 +3,55 @@
|
|
3
3
|
#
|
4
4
|
# Author:: Anupam Sengupta (anupamsg@gmail.com)
|
5
5
|
#
|
6
|
-
# Copyright (c) 2012
|
7
|
-
#
|
6
|
+
# Copyright (c) 2012-2022 Anupam Sengupta. All rights reserved.
|
7
|
+
#
|
8
|
+
# frozen_string_literal: true
|
8
9
|
|
9
10
|
require './lib/tree/version'
|
10
11
|
|
11
12
|
Gem::Specification.new do |s|
|
12
13
|
s.name = 'rubytree'
|
13
|
-
s.date = '2021-12-29'
|
14
14
|
s.version = Tree::VERSION
|
15
15
|
s.license = 'BSD-3-Clause-Clear'
|
16
|
-
|
16
|
+
# NOTE: s.date should NOT be assigned. It is automatically set to pkg date.
|
17
17
|
s.platform = Gem::Platform::RUBY
|
18
18
|
s.author = 'Anupam Sengupta'
|
19
19
|
s.email = 'anupamsg@gmail.com'
|
20
20
|
s.homepage = 'http://rubytree.anupamsg.me'
|
21
21
|
|
22
|
-
s.required_ruby_version = '>=2.
|
22
|
+
s.required_ruby_version = '>=2.6'
|
23
23
|
|
24
|
-
s.summary = 'A generic tree data structure.'
|
25
|
-
s.description = <<-END_OF_TEXT
|
24
|
+
s.summary = 'A generic tree data structure for Ruby.'
|
26
25
|
|
27
|
-
|
28
|
-
|
29
|
-
|
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.
|
30
30
|
|
31
|
-
The implementation is node-centric, where individual nodes in the tree are
|
32
|
-
primary structural elements. All common tree-traversal methods
|
33
|
-
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.
|
34
34
|
|
35
|
-
The library mixes in the Enumerable and Comparable modules to allow access
|
36
|
-
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.).
|
37
37
|
|
38
38
|
A Binary tree is also provided, which provides the in-order traversal in
|
39
39
|
addition to the other methods.
|
40
40
|
|
41
|
-
RubyTree supports importing from, and exporting to JSON, and also supports
|
42
|
-
Ruby's standard object marshaling.
|
41
|
+
RubyTree supports importing from, and exporting to JSON, and also supports
|
42
|
+
the Ruby's standard object marshaling.
|
43
43
|
|
44
44
|
This is a BSD licensed open source project, and is hosted at
|
45
|
-
|
46
|
-
|
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>.
|
47
49
|
|
48
|
-
|
50
|
+
END_DESC
|
49
51
|
|
50
|
-
|
52
|
+
s.metadata = {
|
53
|
+
'rubygems_mfa_required' => 'true'
|
54
|
+
}
|
51
55
|
|
52
56
|
s.files = Dir['lib/**/*.rb'] # The actual code
|
53
57
|
s.files += Dir['[A-Z]*'] # Various documentation files
|
@@ -55,36 +59,55 @@ Gem::Specification.new do |s|
|
|
55
59
|
s.files += Dir['spec/**/*.rb'] # Rspec Test cases
|
56
60
|
s.files += Dir['examples/**/*.rb'] # Examples
|
57
61
|
|
62
|
+
# @todo: Check if this is really needed.
|
58
63
|
s.files += ['.gemtest'] # Support for gem-test
|
59
64
|
|
60
65
|
s.require_paths = ['lib']
|
61
66
|
|
62
67
|
s.test_files = Dir.glob('test/**/test_*.rb')
|
63
68
|
|
64
|
-
s.extra_rdoc_files = %w[README.md LICENSE.md API-CHANGES.
|
65
|
-
s.rdoc_options = ['--title',
|
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']
|
66
73
|
|
67
|
-
s.add_runtime_dependency 'json', '~> 2.
|
68
|
-
s.add_runtime_dependency 'structured_warnings', '~> 0.4.0'
|
74
|
+
s.add_runtime_dependency 'json', '~> 2.0', '> 2.3.1'
|
69
75
|
|
70
|
-
#
|
71
|
-
s.add_development_dependency 'bundler', '~> 2.3
|
72
|
-
s.add_development_dependency '
|
73
|
-
s.add_development_dependency '
|
74
|
-
s.add_development_dependency '
|
75
|
-
s.add_development_dependency 'rspec', '~> 3.10.0'
|
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'
|
76
81
|
s.add_development_dependency 'rtagstask', '~> 0.0.4'
|
77
|
-
s.add_development_dependency 'rubocop', '
|
78
|
-
s.add_development_dependency '
|
79
|
-
s.add_development_dependency '
|
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'
|
80
87
|
|
81
|
-
s.post_install_message = <<-
|
88
|
+
s.post_install_message = <<-END_MESSAGE
|
82
89
|
========================================================================
|
83
90
|
Thank you for installing RubyTree.
|
84
91
|
|
85
|
-
Note::
|
92
|
+
Note::
|
93
|
+
|
94
|
+
- 2.0.0 is a major release with BREAKING API changes.
|
95
|
+
See `API-CHANGES.md` for details.
|
96
|
+
|
97
|
+
- `Tree::TreeNode#depth` method has been removed (it was broken).
|
98
|
+
|
99
|
+
- Support for `CamelCase` methods names has bee removed.
|
100
|
+
|
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.
|
106
|
+
|
107
|
+
- `structured_warnings` is no longer a dependency.
|
108
|
+
|
109
|
+
- Explicit support for rbx Ruby has been removed.
|
86
110
|
|
87
|
-
Details of the API changes are documented in the API-CHANGES file.
|
88
111
|
========================================================================
|
89
|
-
|
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
12
|
require 'tree'
|