walkabout 0.3.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 +7 -0
- data/CHANGELOG +40 -0
- data/LICENSE +21 -0
- data/README.md +98 -0
- data/Rakefile +7 -0
- data/lib/Walkabout/CycleError.rb +15 -0
- data/lib/Walkabout/DAG.rb +78 -0
- data/lib/Walkabout/Node.rb +25 -0
- data/lib/Walkabout/VERSION.rb +6 -0
- data/lib/walkabout.rb +6 -0
- data/test/Walkabout/DAG_test.rb +87 -0
- data/test/Walkabout/Node_test.rb +29 -0
- data/walkabout.gemspec +38 -0
- metadata +81 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: bb6d40e1b5e2ed9cce8ec9546160fcc140db88d7a832f7f49a9864e801e67c86
|
|
4
|
+
data.tar.gz: 06eb640637694a06b5f6bf7d32ef02bfb74cda68b3b1b9f29844eb2ccc1affa9
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 7d16e23d55b2b8ceb2c5a3aef3c54037a7ed6ec7a77b9d3b130cb060486c66cd291d822496f3be80cf4aab7a11142a7cc880d5ca5ea092c7545301b79a678e4d
|
|
7
|
+
data.tar.gz: d7d6548a4c0a4bf81f9f0e33d1969b7ac92dcda796b73aa92da9d1e2f4512c8bcf44ddfee949b57728bb2a390c6363614d312659aa0604168d408958d60d81dd
|
data/CHANGELOG
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# walkabout/CHANGELOG
|
|
2
|
+
|
|
3
|
+
## 20261024
|
|
4
|
+
|
|
5
|
+
0.3.0: + cycle detection; + walkabout(.rb).gemspec
|
|
6
|
+
|
|
7
|
+
1. + lib/walkabout.rb
|
|
8
|
+
2. + lib/Walkabout/CycleError.rb: CycleError#nodes, the nodes on a cycle, or on a path between two
|
|
9
|
+
3. ~ DAG#initialize: + check_for_cycles, raising CycleError. A cycle left none of its nodes ever ready, so complete? was true with them not done.
|
|
10
|
+
4. + DAG#cyclic_nodes, + DAG#nodes_with_predecessor_and_successor_among
|
|
11
|
+
5. ~ DAG.parse: flat_map, rather than map for its side effect
|
|
12
|
+
6. ~ DAG.parse_sequence: each_cons(2).to_a
|
|
13
|
+
7. + lib/Walkabout/VERSION.rb
|
|
14
|
+
8. + test/Walkabout/DAG_test.rb, + test/Walkabout/Node_test.rb
|
|
15
|
+
9. + walkabout.gemspec, + walkabout.rb.gemspec: the same gem published under both names
|
|
16
|
+
10. + Rakefile, + README.md, + CHANGELOG, + LICENSE, + TODO
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
## 20260428
|
|
20
|
+
|
|
21
|
+
0.2.0: /Walkabout::DAG::Node/Walkabout::Node/; nodes held per DAG; /DAG#next/DAG#take/
|
|
22
|
+
|
|
23
|
+
1. + lib/Walkabout/Node.rb: Node, out of DAG, + Node#name
|
|
24
|
+
2. ~ DAG#initialize: nodes held in @nodes, rather than on the Node class, so that more than one DAG may exist at once
|
|
25
|
+
3. /DAG#next/DAG#take/: take(n) hands out up to n ready nodes
|
|
26
|
+
4. ~ DAG#ready: private
|
|
27
|
+
5. - lib/Walkabout/DAG.rb: the example
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
## 20260423
|
|
31
|
+
|
|
32
|
+
0.1.0: + Walkabout::DAG::Node; + DAG#ready, #next, #complete?
|
|
33
|
+
|
|
34
|
+
1. + DAG::Node: predecessors, complete!, complete?
|
|
35
|
+
2. ~ DAG.parse: returns a DAG, rather than the edges
|
|
36
|
+
3. ~ lib/Walkabout/DAG.rb: the example takes the next node and completes it
|
|
37
|
+
|
|
38
|
+
0.0.0: + Walkabout::DAG.parse
|
|
39
|
+
|
|
40
|
+
1. + lib/Walkabout/DAG.rb: DAG.parse, and an example of it parsing three sequences
|
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 thoran
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# walkabout
|
|
2
|
+
|
|
3
|
+
Walk a directed acyclic graph in dependency order.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
gem install walkabout
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Or add to your Gemfile:
|
|
12
|
+
|
|
13
|
+
```ruby
|
|
14
|
+
gem 'walkabout'
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
```ruby
|
|
20
|
+
require 'walkabout'
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Building a DAG
|
|
24
|
+
|
|
25
|
+
From edges, each a pair of predecessor and successor:
|
|
26
|
+
|
|
27
|
+
```ruby
|
|
28
|
+
dag = Walkabout::DAG.new([[:a, :b], [:b, :c], [:d, :b]])
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Or from sequences, each of which is read as edges between its consecutive
|
|
32
|
+
members, and which join at the members they share:
|
|
33
|
+
|
|
34
|
+
```ruby
|
|
35
|
+
dag = Walkabout::DAG.parse([
|
|
36
|
+
[:a, :b, :c],
|
|
37
|
+
[:d, :b, :e],
|
|
38
|
+
[:f, :g]
|
|
39
|
+
])
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Nodes are made from the names in the edges, and so a node appears only where it
|
|
43
|
+
is in at least one edge.
|
|
44
|
+
|
|
45
|
+
### Walking it
|
|
46
|
+
|
|
47
|
+
A node is ready once it is incomplete and each of its predecessors is complete.
|
|
48
|
+
`take` hands out the first ready node, or `nil`; `take(n)` up to n of them, as
|
|
49
|
+
an array:
|
|
50
|
+
|
|
51
|
+
```ruby
|
|
52
|
+
while (node = dag.take)
|
|
53
|
+
puts node.name
|
|
54
|
+
node.complete!
|
|
55
|
+
end
|
|
56
|
+
dag.complete? # => true
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
`take` does not record that a node has been handed out, so a node taken and not
|
|
60
|
+
yet completed is handed out again. A batch from `take(n)` is therefore to be
|
|
61
|
+
completed before the next is taken.
|
|
62
|
+
|
|
63
|
+
### Cycles
|
|
64
|
+
|
|
65
|
+
A DAG with a cycle raises `Walkabout::CycleError` when it is built, rather than
|
|
66
|
+
leaving the nodes on the cycle never ready. Its `nodes` are the nodes on the
|
|
67
|
+
cycle, or on a path between two cycles:
|
|
68
|
+
|
|
69
|
+
```ruby
|
|
70
|
+
Walkabout::DAG.new([[:x, :a], [:a, :b], [:b, :a]])
|
|
71
|
+
# => Walkabout::CycleError: cycle among: a, b
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Subclassing
|
|
75
|
+
|
|
76
|
+
`Walkabout::Node` and `Walkabout::DAG` are meant to be subclassed, a node
|
|
77
|
+
carrying whatever the walk is to do:
|
|
78
|
+
|
|
79
|
+
```ruby
|
|
80
|
+
class Step < Walkabout::Node
|
|
81
|
+
def run
|
|
82
|
+
puts "running #{name}"
|
|
83
|
+
complete!
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Contributing
|
|
89
|
+
|
|
90
|
+
1. Fork it [https://github.com/thoran/walkabout/fork](https://github.com/thoran/walkabout/fork)
|
|
91
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
|
92
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
|
93
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
|
94
|
+
5. Create a new pull request
|
|
95
|
+
|
|
96
|
+
## License
|
|
97
|
+
|
|
98
|
+
MIT
|
data/Rakefile
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Walkabout/CycleError.rb
|
|
2
|
+
# Walkabout::CycleError
|
|
3
|
+
|
|
4
|
+
module Walkabout
|
|
5
|
+
class CycleError < StandardError
|
|
6
|
+
attr_reader :nodes
|
|
7
|
+
|
|
8
|
+
private
|
|
9
|
+
|
|
10
|
+
def initialize(nodes)
|
|
11
|
+
@nodes = nodes
|
|
12
|
+
super("cycle among: #{nodes.map(&:name).join(', ')}")
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Walkabout/DAG.rb
|
|
2
|
+
# Walkabout::DAG
|
|
3
|
+
|
|
4
|
+
require_relative 'CycleError'
|
|
5
|
+
require_relative 'Node'
|
|
6
|
+
|
|
7
|
+
module Walkabout
|
|
8
|
+
class DAG
|
|
9
|
+
class << self
|
|
10
|
+
def parse(sequences)
|
|
11
|
+
self.new(sequences.flat_map{|s| parse_sequence(s)})
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
private
|
|
15
|
+
|
|
16
|
+
def parse_sequence(sequence)
|
|
17
|
+
sequence.each_cons(2).to_a
|
|
18
|
+
end
|
|
19
|
+
end # class << self
|
|
20
|
+
|
|
21
|
+
def take(n = nil)
|
|
22
|
+
if n
|
|
23
|
+
ready.first(n)
|
|
24
|
+
else
|
|
25
|
+
ready.first
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def complete?
|
|
30
|
+
ready.empty?
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
def initialize(edges)
|
|
36
|
+
@nodes = build_nodes(edges)
|
|
37
|
+
check_for_cycles
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def build_nodes(edges)
|
|
41
|
+
nodes = {}
|
|
42
|
+
edges.each do |a, b|
|
|
43
|
+
predecessor = (nodes[a] ||= Node.new(a))
|
|
44
|
+
successor = (nodes[b] ||= Node.new(b))
|
|
45
|
+
successor.predecessors << predecessor
|
|
46
|
+
end
|
|
47
|
+
nodes.values
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def check_for_cycles
|
|
51
|
+
nodes = cyclic_nodes
|
|
52
|
+
raise CycleError.new(nodes) unless nodes.empty?
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Trims, until nothing more goes, every node with no predecessor or no
|
|
56
|
+
# successor left among those remaining. Only nodes on a cycle, or on a path
|
|
57
|
+
# between two, survive.
|
|
58
|
+
def cyclic_nodes
|
|
59
|
+
nodes = @nodes
|
|
60
|
+
while (trimmed = nodes_with_predecessor_and_successor_among(nodes)) != nodes
|
|
61
|
+
nodes = trimmed
|
|
62
|
+
end
|
|
63
|
+
nodes
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def nodes_with_predecessor_and_successor_among(nodes)
|
|
67
|
+
nodes.select do |node|
|
|
68
|
+
node.predecessors.any?{|p| nodes.include?(p)} && nodes.any?{|n| n.predecessors.include?(node)}
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def ready
|
|
73
|
+
@nodes.select do |n|
|
|
74
|
+
!n.complete? && n.predecessors.all?(&:complete?)
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Walkabout/Node.rb
|
|
2
|
+
# Walkabout::Node
|
|
3
|
+
|
|
4
|
+
module Walkabout
|
|
5
|
+
class Node
|
|
6
|
+
attr_accessor :name
|
|
7
|
+
attr_accessor :predecessors
|
|
8
|
+
|
|
9
|
+
def complete!
|
|
10
|
+
@complete = true
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def complete?
|
|
14
|
+
@complete
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
private
|
|
18
|
+
|
|
19
|
+
def initialize(name, predecessors = [])
|
|
20
|
+
@name = name
|
|
21
|
+
@predecessors = predecessors
|
|
22
|
+
@complete = false
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
data/lib/walkabout.rb
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# test/Walkabout/DAG_test.rb
|
|
2
|
+
|
|
3
|
+
require 'minitest/autorun'
|
|
4
|
+
|
|
5
|
+
require_relative '../../lib/Walkabout/DAG'
|
|
6
|
+
|
|
7
|
+
describe Walkabout::DAG do
|
|
8
|
+
def names(nodes)
|
|
9
|
+
nodes.map(&:name)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
describe '.parse' do
|
|
13
|
+
it 'turns each sequence into edges between consecutive members' do
|
|
14
|
+
dag = Walkabout::DAG.parse([[:a, :b, :c], [:d, :b, :e]])
|
|
15
|
+
_(names(dag.take(5))).must_equal [:a, :d]
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it 'joins sequences at the members they share' do
|
|
19
|
+
dag = Walkabout::DAG.parse([[:a, :b], [:c, :b]])
|
|
20
|
+
dag.take.complete!
|
|
21
|
+
_(names(dag.take(5))).must_equal [:c]
|
|
22
|
+
dag.take.complete!
|
|
23
|
+
_(names(dag.take(5))).must_equal [:b]
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
describe '#take' do
|
|
28
|
+
it 'returns the first ready node when given no count' do
|
|
29
|
+
dag = Walkabout::DAG.new([[:a, :b]])
|
|
30
|
+
_(dag.take.name).must_equal :a
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it 'returns up to n ready nodes when given a count' do
|
|
34
|
+
dag = Walkabout::DAG.parse([[:a, :d], [:b, :d], [:c, :d]])
|
|
35
|
+
_(names(dag.take(2))).must_equal [:a, :b]
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it 'returns a node only once its predecessors are complete' do
|
|
39
|
+
dag = Walkabout::DAG.parse([[:a, :b, :c]])
|
|
40
|
+
_(names(dag.take(5))).must_equal [:a]
|
|
41
|
+
dag.take.complete!
|
|
42
|
+
_(names(dag.take(5))).must_equal [:b]
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it 'returns nil, or an empty array, when nothing is ready' do
|
|
46
|
+
dag = Walkabout::DAG.new([])
|
|
47
|
+
_(dag.take).must_be_nil
|
|
48
|
+
_(dag.take(2)).must_equal []
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
describe '#complete?' do
|
|
53
|
+
it 'is false while any node is incomplete' do
|
|
54
|
+
dag = Walkabout::DAG.new([[:a, :b]])
|
|
55
|
+
dag.take.complete!
|
|
56
|
+
_(dag.complete?).must_equal false
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
it 'is true once every node is complete' do
|
|
60
|
+
dag = Walkabout::DAG.parse([[:a, :b, :c], [:d, :b]])
|
|
61
|
+
while (node = dag.take)
|
|
62
|
+
node.complete!
|
|
63
|
+
end
|
|
64
|
+
_(dag.complete?).must_equal true
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
describe 'cycles' do
|
|
69
|
+
it 'raises CycleError for a cycle' do
|
|
70
|
+
_{Walkabout::DAG.new([[:a, :b], [:b, :a]])}.must_raise Walkabout::CycleError
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
it 'raises CycleError for a node which is its own predecessor' do
|
|
74
|
+
_{Walkabout::DAG.new([[:a, :a]])}.must_raise Walkabout::CycleError
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
it 'names only the nodes on the cycle, and not those before or after it' do
|
|
78
|
+
error = _{Walkabout::DAG.parse([[:x, :a, :b, :c, :a], [:c, :y]])}.must_raise Walkabout::CycleError
|
|
79
|
+
_(names(error.nodes).sort).must_equal [:a, :b, :c]
|
|
80
|
+
_(error.message).must_equal 'cycle among: a, b, c'
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
it 'does not raise where paths diverge and rejoin' do
|
|
84
|
+
_(Walkabout::DAG.parse([[:a, :b, :d], [:a, :c, :d]]).take.name).must_equal :a
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# test/Walkabout/Node_test.rb
|
|
2
|
+
|
|
3
|
+
require 'minitest/autorun'
|
|
4
|
+
|
|
5
|
+
require_relative '../../lib/Walkabout/Node'
|
|
6
|
+
|
|
7
|
+
describe Walkabout::Node do
|
|
8
|
+
describe '.new' do
|
|
9
|
+
it 'has a name' do
|
|
10
|
+
_(Walkabout::Node.new(:a).name).must_equal :a
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it 'has no predecessors by default' do
|
|
14
|
+
_(Walkabout::Node.new(:a).predecessors).must_equal []
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it 'is not complete' do
|
|
18
|
+
_(Walkabout::Node.new(:a).complete?).must_equal false
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
describe '#complete!' do
|
|
23
|
+
it 'makes the node complete' do
|
|
24
|
+
node = Walkabout::Node.new(:a)
|
|
25
|
+
node.complete!
|
|
26
|
+
_(node.complete?).must_equal true
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
data/walkabout.gemspec
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
require_relative './lib/Walkabout/VERSION'
|
|
2
|
+
|
|
3
|
+
class Gem::Specification
|
|
4
|
+
def development_dependencies=(gems)
|
|
5
|
+
gems.each{|gem| add_development_dependency(*gem)}
|
|
6
|
+
end
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
Gem::Specification.new do |spec|
|
|
10
|
+
spec.name = 'walkabout'
|
|
11
|
+
spec.version = Walkabout::VERSION
|
|
12
|
+
|
|
13
|
+
spec.summary = "Walk a directed acyclic graph in dependency order."
|
|
14
|
+
spec.description = "Walk a directed acyclic graph in dependency order. A DAG built from edges, or from sequences, hands out the nodes whose predecessors are complete, singly or in batches, and refuses a graph with a cycle."
|
|
15
|
+
|
|
16
|
+
spec.author = 'thoran'
|
|
17
|
+
spec.email = 'code@thoran.com'
|
|
18
|
+
spec.homepage = 'https://github.com/thoran/walkabout'
|
|
19
|
+
spec.license = 'MIT'
|
|
20
|
+
|
|
21
|
+
spec.required_ruby_version = '>= 3'
|
|
22
|
+
spec.require_paths = ['lib']
|
|
23
|
+
|
|
24
|
+
spec.files = [
|
|
25
|
+
'walkabout.gemspec',
|
|
26
|
+
Dir['lib/**/*.rb'],
|
|
27
|
+
Dir['test/**/*.rb'],
|
|
28
|
+
'CHANGELOG',
|
|
29
|
+
'LICENSE',
|
|
30
|
+
'Rakefile',
|
|
31
|
+
'README.md',
|
|
32
|
+
].flatten
|
|
33
|
+
|
|
34
|
+
spec.development_dependencies = %w{
|
|
35
|
+
rake
|
|
36
|
+
minitest
|
|
37
|
+
}
|
|
38
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: walkabout
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.3.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- thoran
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: rake
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '0'
|
|
19
|
+
type: :development
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '0'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: minitest
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - ">="
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '0'
|
|
33
|
+
type: :development
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - ">="
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '0'
|
|
40
|
+
description: Walk a directed acyclic graph in dependency order. A DAG built from edges,
|
|
41
|
+
or from sequences, hands out the nodes whose predecessors are complete, singly or
|
|
42
|
+
in batches, and refuses a graph with a cycle.
|
|
43
|
+
email: code@thoran.com
|
|
44
|
+
executables: []
|
|
45
|
+
extensions: []
|
|
46
|
+
extra_rdoc_files: []
|
|
47
|
+
files:
|
|
48
|
+
- CHANGELOG
|
|
49
|
+
- LICENSE
|
|
50
|
+
- README.md
|
|
51
|
+
- Rakefile
|
|
52
|
+
- lib/Walkabout/CycleError.rb
|
|
53
|
+
- lib/Walkabout/DAG.rb
|
|
54
|
+
- lib/Walkabout/Node.rb
|
|
55
|
+
- lib/Walkabout/VERSION.rb
|
|
56
|
+
- lib/walkabout.rb
|
|
57
|
+
- test/Walkabout/DAG_test.rb
|
|
58
|
+
- test/Walkabout/Node_test.rb
|
|
59
|
+
- walkabout.gemspec
|
|
60
|
+
homepage: https://github.com/thoran/walkabout
|
|
61
|
+
licenses:
|
|
62
|
+
- MIT
|
|
63
|
+
metadata: {}
|
|
64
|
+
rdoc_options: []
|
|
65
|
+
require_paths:
|
|
66
|
+
- lib
|
|
67
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
68
|
+
requirements:
|
|
69
|
+
- - ">="
|
|
70
|
+
- !ruby/object:Gem::Version
|
|
71
|
+
version: '3'
|
|
72
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
73
|
+
requirements:
|
|
74
|
+
- - ">="
|
|
75
|
+
- !ruby/object:Gem::Version
|
|
76
|
+
version: '0'
|
|
77
|
+
requirements: []
|
|
78
|
+
rubygems_version: 4.0.22
|
|
79
|
+
specification_version: 4
|
|
80
|
+
summary: Walk a directed acyclic graph in dependency order.
|
|
81
|
+
test_files: []
|