drain 0.1.0 → 0.2.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.
Files changed (46) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +6 -2
  3. data/.travis.yml +10 -0
  4. data/.yardopts +6 -1
  5. data/Gemfile +7 -0
  6. data/LICENSE.txt +1 -1
  7. data/README.md +11 -5
  8. data/Rakefile +7 -12
  9. data/drain.gemspec +15 -5
  10. data/gemspec.yml +4 -3
  11. data/lib/dr.rb +1 -0
  12. data/lib/{drain → dr}/base.rb +0 -0
  13. data/lib/{drain → dr}/base/bool.rb +0 -0
  14. data/lib/dr/base/converter.rb +33 -0
  15. data/lib/{drain → dr}/base/encoding.rb +0 -0
  16. data/lib/dr/base/eruby.rb +284 -0
  17. data/lib/{drain → dr}/base/functional.rb +2 -2
  18. data/lib/dr/base/graph.rb +378 -0
  19. data/lib/dr/base/utils.rb +28 -0
  20. data/lib/dr/parse.rb +1 -0
  21. data/lib/dr/parse/simple_parser.rb +70 -0
  22. data/lib/{drain → dr}/parse/time_parse.rb +0 -0
  23. data/lib/dr/ruby_ext.rb +1 -0
  24. data/lib/dr/ruby_ext/core_ext.rb +7 -0
  25. data/lib/{drain/ruby_ext/core_ext.rb → dr/ruby_ext/core_modules.rb} +67 -27
  26. data/lib/{drain → dr}/ruby_ext/meta_ext.rb +57 -30
  27. data/lib/dr/tools.rb +1 -0
  28. data/lib/{drain → dr}/tools/gtk.rb +0 -0
  29. data/lib/dr/version.rb +4 -0
  30. data/lib/drain.rb +2 -1
  31. data/test/helper.rb +12 -1
  32. data/test/test_converter.rb +42 -0
  33. data/test/test_core_ext.rb +116 -0
  34. data/test/test_graph.rb +126 -0
  35. data/test/test_meta.rb +65 -0
  36. data/test/test_simple_parser.rb +41 -0
  37. metadata +45 -21
  38. data/.document +0 -3
  39. data/lib/drain/base/eruby.rb +0 -28
  40. data/lib/drain/base/graph.rb +0 -213
  41. data/lib/drain/parse.rb +0 -5
  42. data/lib/drain/parse/simple_parser.rb +0 -61
  43. data/lib/drain/ruby_ext.rb +0 -5
  44. data/lib/drain/tools.rb +0 -5
  45. data/lib/drain/tools/git.rb +0 -116
  46. data/lib/drain/version.rb +0 -4
@@ -0,0 +1,126 @@
1
+ require 'helper'
2
+ require 'dr/base/graph'
3
+
4
+ # This segfaults in ruby-2.2.0, but seems corrected in ruby-2.3-dev
5
+ describe DR::Graph do
6
+ before do
7
+ @graph=DR::Graph.new({"foo"=> ["bar","baz"], "bar" => "baz"})
8
+ end
9
+
10
+ it "builds the graph" do
11
+ @graph.nodes.length.must_equal 3
12
+ end
13
+
14
+ it "accepts :to_a" do
15
+ @graph.to_a.map(&:name).must_equal(["foo", "bar", "baz"])
16
+ end
17
+
18
+ it "accepts :to_hash" do
19
+ @graph.to_hash.first[1].keys.must_equal [:children, :parents, :attributes]
20
+ end
21
+
22
+ it "can be converted to a hash" do
23
+ @graph.to_h.must_equal ({"foo"=> ["bar","baz"], "bar" => ["baz"], "baz" => []})
24
+ end
25
+
26
+ it "can give a node" do
27
+ @graph["foo"].class.must_equal DR::Node
28
+ end
29
+
30
+ it "can give descendants of a node" do
31
+ @graph["foo"].descendants.map(&:to_s).must_equal(["bar", "baz"])
32
+ end
33
+
34
+ it "can give ancestors of a node" do
35
+ @graph["baz"].ancestors.map(&:to_s).must_equal(["foo", "bar"])
36
+ end
37
+
38
+ it "can give the root nodes" do
39
+ @graph.roots.map(&:name).must_equal(["foo"])
40
+ end
41
+
42
+ it "can give the bottom nodes" do
43
+ @graph.bottom.map(&:name).must_equal(["baz"])
44
+ end
45
+
46
+ it "can show all ancestors of nodes" do
47
+ @graph.ancestors("baz","bar").map(&:to_s).must_equal(["baz", "bar", "foo"])
48
+ @graph.ancestors("baz","bar", ourselves: false).map(&:to_s).must_equal(["foo"])
49
+ end
50
+
51
+ it "can show all descendants of nodes" do
52
+ @graph.descendants("foo","bar").map(&:to_s).must_equal(["foo", "bar", "baz"])
53
+ @graph.descendants("foo","bar", ourselves: false).map(&:to_s).must_equal(["baz"])
54
+ end
55
+
56
+ it "can give a hash of children" do
57
+ @graph.to_children.must_equal({"foo"=>["bar", "baz"], "bar"=>["baz"], "baz"=>[]})
58
+ end
59
+
60
+ describe "build" do
61
+ it "accepts a Hash" do
62
+ @graph.build({"plim" => "foo"})
63
+ end
64
+ end
65
+
66
+ it "detects unneeded nodes" do
67
+ @graph.unneeded("foo","bar").map(&:name).must_equal ["foo","bar"]
68
+ @graph.unneeded("bar").map(&:name).must_equal []
69
+ end
70
+ it "detects unneeded descendants" do
71
+ @graph.unneeded_descendants("foo").map(&:name).must_equal ["foo", "bar", "baz"]
72
+ end
73
+
74
+ describe "It works with a cycle" do
75
+ before do
76
+ @graph=DR::Graph.new({"foo"=> ["bar","baz"], "bar" => ["baz"], "baz" => "foo"})
77
+ end
78
+
79
+ it "It builds the graph" do
80
+ @graph.nodes.length.must_equal 3
81
+ end
82
+ end
83
+
84
+ describe "It works with a lambda to describe the graph" do
85
+ before do
86
+ infos=-> (node) do
87
+ case node
88
+ when "foo"
89
+ return {children: ["bar","baz"]}
90
+ when "bar"
91
+ return {children: ["baz"]}
92
+ when "baz"
93
+ return {children: "foo", attributes: {real: true}}
94
+ end
95
+ end
96
+ @graph=DR::Graph.new(*["foo","bar","baz"],infos: infos)
97
+ end
98
+
99
+ it "It builds the graph" do
100
+ @graph.nodes.length.must_equal 3
101
+ @graph.to_h.must_equal({"foo"=>["bar", "baz"], "bar"=>["baz"], "baz"=>["foo"]})
102
+ @graph['baz'].attributes.must_equal(real: true)
103
+ end
104
+ end
105
+
106
+ describe "It can be merged with another graph" do
107
+ before do
108
+ @graph2=DR::Graph.new({"foo" => ["bar"], "baz" => ["bar", "qux"]})
109
+ end
110
+
111
+ it "Graph2 is well defined" do
112
+ @graph2.nodes.map(&:name).must_equal(%w(foo bar baz qux))
113
+ end
114
+
115
+ it "Can be merged in place" do
116
+ @graph | @graph2
117
+ @graph.to_h.must_equal({"foo"=>["bar", "baz"], "bar"=>["baz"], "baz"=>["bar", "qux"], "qux"=>[]})
118
+ end
119
+
120
+ it "Can be merged" do
121
+ @graph3 = @graph + @graph2
122
+ @graph.to_h.must_equal({"foo"=>["bar", "baz"], "bar"=>["baz"], "baz"=>[]})
123
+ @graph3.to_h.must_equal({"foo"=>["bar", "baz"], "bar"=>["baz"], "baz"=>["bar", "qux"], "qux"=>[]})
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,65 @@
1
+ require "helper"
2
+ require 'dr/ruby_ext/meta_ext'
3
+ #Module.send :include, DR::Meta
4
+
5
+ class TestMetaExt < Minitest::Test
6
+ def setup
7
+ @foo=Module.new do
8
+ extend DR::MetaModule
9
+ def foo
10
+ "foo"
11
+ end
12
+ end
13
+ @bar=Module.new do
14
+ def bar
15
+ "bar"
16
+ end
17
+ end
18
+ @baz=Module.new do
19
+ def baz
20
+ "baz"
21
+ end
22
+ end
23
+ @foo.includes_extends_host_with(@bar,@baz)
24
+ end
25
+ def test_includes
26
+ klass=@foo
27
+ test1=Class.new do
28
+ include klass
29
+ end
30
+ test1.new.foo
31
+ test1.new.bar
32
+ test1.baz
33
+ end
34
+ def test_extends
35
+ klass=@foo
36
+ test1=Class.new do
37
+ extend klass
38
+ end
39
+ test1.foo
40
+ test1.new.bar
41
+ test1.baz
42
+ end
43
+ end
44
+
45
+ describe DR::Meta do
46
+ ## Does not work anymore in recent rubies (ruby 2.4+)
47
+ # it "Can convert a class to module" do
48
+ # (Class.new { include DR::Meta.refined_module(String) { def length; super+5; end } }).new("foo").length.must_equal(8)
49
+ # end
50
+
51
+ it "Can show all ancestors" do
52
+ DR::Meta.all_ancestors("foo").include?(String.singleton_class).must_equal(true)
53
+ end
54
+
55
+ it "Can generate bound methods" do
56
+ m=DR::Meta.get_bound_method("foo", :bar) do |x|
57
+ self+x
58
+ end
59
+ m.call("bar").must_equal("foobar")
60
+ end
61
+
62
+ it "Can apply unbound methods" do
63
+ DR::Meta.apply(method: String.instance_method(:length), to: "foo").must_equal(3)
64
+ end
65
+ end
@@ -0,0 +1,41 @@
1
+ require 'helper'
2
+ require 'dr/parse/simple_parser'
3
+
4
+ describe DR::SimpleParser do
5
+ describe "parse_namevalue" do
6
+ it "parses a simple name value" do
7
+ DR::SimpleParser.parse_namevalue("foo:bar").must_equal([:foo,"bar"])
8
+ end
9
+ it "can let the name be a string" do
10
+ DR::SimpleParser.parse_namevalue("foo:bar",symbolize:false).must_equal(["foo","bar"])
11
+ end
12
+ it "only splits on the first ':'" do
13
+ DR::SimpleParser.parse_namevalue("foo:bar:baz").must_equal([:foo,"bar:baz"])
14
+ end
15
+ it "can change the separation" do
16
+ DR::SimpleParser.parse_namevalue("foo:bar!baz", sep: "!",symbolize:false).must_equal(["foo:bar","baz"])
17
+ end
18
+ it "can set a default" do
19
+ DR::SimpleParser.parse_namevalue("foo", default: 0).must_equal([:foo,0])
20
+ end
21
+ it "If the default is true then support 'no-foo'" do
22
+ DR::SimpleParser.parse_namevalue("no-foo", default: true).must_equal([:foo,false])
23
+ end
24
+ it "can set the default to true" do
25
+ DR::SimpleParser.parse_namevalue("foo", default: true, symbolize:false).must_equal(["foo",true])
26
+ end
27
+ end
28
+
29
+ describe "parse_strings" do
30
+ it "can parse several name values" do
31
+ DR::SimpleParser.parse_string("foo:bar,ploum:plim")[:values].must_equal({foo: "bar", ploum: "plim"})
32
+ end
33
+ it "can handle options" do
34
+ DR::SimpleParser.parse_string("name1:value1!option1=ploum!option2=plam!option3,name2:value2!!globalopt1=foo,globalopt2=bar").must_equal({
35
+ values: {name1: "value1", name2: "value2"},
36
+ local_opts: {name1: {option1:"ploum",option2:"plam",option3:true}, name2: {}},
37
+ global_opts: {globalopt1: "foo", globalopt2: "bar"},
38
+ opts: {name1: {option1:"ploum",option2:"plam",option3:true,globalopt1:"foo", globalopt2: "bar"}, name2:{globalopt1: "foo", globalopt2: "bar"}}})
39
+ end
40
+ end
41
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: drain
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Damien Robert
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-24 00:00:00.000000000 Z
11
+ date: 2018-02-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '5.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: rubygems-tasks
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -63,38 +77,48 @@ extra_rdoc_files:
63
77
  - LICENSE.txt
64
78
  - README.md
65
79
  files:
66
- - ".document"
67
80
  - ".gitignore"
81
+ - ".travis.yml"
68
82
  - ".yardopts"
69
83
  - ChangeLog.md
84
+ - Gemfile
70
85
  - LICENSE.txt
71
86
  - README.md
72
87
  - Rakefile
73
88
  - drain.gemspec
74
89
  - gemspec.yml
90
+ - lib/dr.rb
91
+ - lib/dr/base.rb
92
+ - lib/dr/base/bool.rb
93
+ - lib/dr/base/converter.rb
94
+ - lib/dr/base/encoding.rb
95
+ - lib/dr/base/eruby.rb
96
+ - lib/dr/base/functional.rb
97
+ - lib/dr/base/graph.rb
98
+ - lib/dr/base/utils.rb
99
+ - lib/dr/parse.rb
100
+ - lib/dr/parse/simple_parser.rb
101
+ - lib/dr/parse/time_parse.rb
102
+ - lib/dr/ruby_ext.rb
103
+ - lib/dr/ruby_ext/core_ext.rb
104
+ - lib/dr/ruby_ext/core_modules.rb
105
+ - lib/dr/ruby_ext/meta_ext.rb
106
+ - lib/dr/tools.rb
107
+ - lib/dr/tools/gtk.rb
108
+ - lib/dr/version.rb
75
109
  - lib/drain.rb
76
- - lib/drain/base.rb
77
- - lib/drain/base/bool.rb
78
- - lib/drain/base/encoding.rb
79
- - lib/drain/base/eruby.rb
80
- - lib/drain/base/functional.rb
81
- - lib/drain/base/graph.rb
82
- - lib/drain/parse.rb
83
- - lib/drain/parse/simple_parser.rb
84
- - lib/drain/parse/time_parse.rb
85
- - lib/drain/ruby_ext.rb
86
- - lib/drain/ruby_ext/core_ext.rb
87
- - lib/drain/ruby_ext/meta_ext.rb
88
- - lib/drain/tools.rb
89
- - lib/drain/tools/git.rb
90
- - lib/drain/tools/gtk.rb
91
- - lib/drain/version.rb
92
110
  - test/helper.rb
111
+ - test/test_converter.rb
112
+ - test/test_core_ext.rb
93
113
  - test/test_drain.rb
114
+ - test/test_graph.rb
115
+ - test/test_meta.rb
116
+ - test/test_simple_parser.rb
94
117
  homepage: https://github.com/DamienRobert/drain#readme
95
118
  licenses:
96
119
  - MIT
97
- metadata: {}
120
+ metadata:
121
+ yard.run: yri
98
122
  post_install_message:
99
123
  rdoc_options: []
100
124
  require_paths:
@@ -111,7 +135,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
111
135
  version: '0'
112
136
  requirements: []
113
137
  rubyforge_project:
114
- rubygems_version: 2.4.5
138
+ rubygems_version: 2.7.3
115
139
  signing_key:
116
140
  specification_version: 4
117
141
  summary: Use a drain for a dryer ruby!
data/.document DELETED
@@ -1,3 +0,0 @@
1
- -
2
- ChangeLog.md
3
- LICENSE.txt
@@ -1,28 +0,0 @@
1
- module DR
2
- module Eruby
3
- begin
4
- require 'erubis'
5
- Erb=::Erubis::Eruby
6
- rescue LoadError
7
- require 'erb'
8
- Erb=::ERB
9
- end
10
- def erb_include(template, opt={})
11
- opt={bind: binding}.merge(opt)
12
- file=File.expand_path(template)
13
- Dir.chdir(File.dirname(file)) do |cwd|
14
- erb = Erb.new(File.read(file))
15
- #if context is not empty, then we probably want to evaluate
16
- if opt[:evaluate] or opt[:context]
17
- r=erb.evaluate(opt[:context])
18
- else
19
- r=erb.result(opt[:bind])
20
- end
21
- #if using erubis, it is better to invoke the template in <%= =%> than
22
- #to use chop=true
23
- r=r.chomp if opt[:chomp]
24
- return r
25
- end
26
- end
27
- end
28
- end
@@ -1,213 +0,0 @@
1
- require 'set'
2
- #Originally inspired by depgraph: https://github.com/dcadenas/depgraph
3
-
4
- module DR
5
- class Node
6
- include Enumerable
7
- attr_reader :graph
8
- attr_accessor :name, :attributes, :parents, :children
9
- def initialize(name, attributes: nil, graph: nil)
10
- @name = name
11
- @children = []
12
- @parents = []
13
- @attributes = attributes
14
- @graph=graph
15
- graph.nodes << self if @graph
16
- end
17
- def each
18
- @children.each
19
- end
20
- def <=>(other)
21
- return @name <=> other.name
22
- end
23
- #self.add_child(ploum) marks ploum as a child of self (ie ploum depends on self)
24
- def add_child(*nodes)
25
- nodes.each do |node|
26
- if not @children.include?(node)
27
- @children << node
28
- node.parents << self
29
- end
30
- end
31
- end
32
- def rm_child(*nodes)
33
- nodes.each do |node|
34
- if @children.include?(node)
35
- @children.delete(node)
36
- node.parents.delete(self)
37
- end
38
- end
39
- end
40
- def add_parent(*nodes)
41
- nodes.each do |node|
42
- if not @parents.include?(node)
43
- @parents << node
44
- node.children << self
45
- end
46
- end
47
- end
48
- def rm_parent(*nodes)
49
- nodes.each do |node|
50
- if @parents.include?(node)
51
- @parents.delete(node)
52
- node.children.delete(self)
53
- end
54
- end
55
- end
56
-
57
- STEP = 4
58
- def to_s
59
- return @name
60
- end
61
- def to_graph(indent_level: 0)
62
- sout = ""
63
- margin = ''
64
- 0.upto(indent_level/STEP-1) { |p| margin += (p==0 ? ' ' : '|') + ' '*(STEP - 1) }
65
- margin += '|' + '-'*(STEP - 2)
66
- sout += margin + "#{@name}\n"
67
- @children.each do |child|
68
- sout += child.to_graph(indent_level: indent_level+STEP)
69
- end
70
- return sout
71
- end
72
- def to_dot
73
- sout=["\""+name+"\""]
74
- @children.each do |child|
75
- sout.push "\"#{@name}\" -> \"#{child.name}\""
76
- sout += child.to_dot
77
- end
78
- return sout
79
- end
80
- end
81
-
82
- class Graph
83
- attr_accessor :nodes
84
- include Enumerable
85
- def initialize(g=nil)
86
- @nodes=[]
87
- if g #convert a hash to a graph
88
- g.each do |name,children|
89
- n=build(name)
90
- n.add_child(*children)
91
- end
92
- end
93
- end
94
- def build(node, children: [], parents: [], **keywords)
95
- graph_node=
96
- case node
97
- when Node
98
- match = @nodes.find {|n| n == node} and return match
99
- Node.new(node.name, graph: self, **keywords.merge({attributes: node.attributes||keywords[:attributes]}))
100
- node.children.each do |c|
101
- build(c,**keywords)
102
- end
103
- else
104
- match = @nodes.find {|n| n.name == node}
105
- match || Node.new(node, graph: self, **keywords)
106
- end
107
- graph_node.add_child(*children.map { |child| build(child) })
108
- graph_node.add_parent(*parents.map { |child| build(child) })
109
- return graph_node
110
- end
111
- def each
112
- @nodes.each
113
- end
114
- def to_a
115
- return @nodes
116
- end
117
- def all
118
- @nodes.sort
119
- end
120
- def roots
121
- @nodes.select{ |n| n.parents.length == 0}.sort
122
- end
123
- def dump(mode: :graph, nodes_list: :roots, **unused)
124
- n=case nodes_list
125
- when :roots; roots
126
- when :all; all
127
- when Symbol; nodes.select {|n| n.attributes[:nodes_list]}
128
- else nodes_list.to_a
129
- end
130
- sout = ""
131
- case mode
132
- when :graph; n.each do |node| sout+=node.to_graph end
133
- when :list; n.each do |i| sout+="- #{i}\n" end
134
- when :dot;
135
- sout+="digraph gems {\n"
136
- sout+=n.map {|node| node.to_dot}.inject(:+).uniq!.join("\n")
137
- sout+="}\n"
138
- end
139
- return sout
140
- end
141
-
142
- #return the connected set containing nodes (following the direction
143
- #given)
144
- def connected(*nodes, down:true, up:true)
145
- r=Set.new()
146
- nodes.each do |node|
147
- unless r.include?(node)
148
- new_nodes=Set.new()
149
- new_nodes.merge(node.children) if down
150
- new_nodes.merge(node.parents) if up
151
- r.merge(connected(*new_nodes, down:down,up:up))
152
- end
153
- end
154
- return r
155
- end
156
- #return all parents
157
- def ancestors(*nodes)
158
- connected(*nodes, up:true, down:false)
159
- end
160
- #return all childern
161
- def descendants(*nodes)
162
- connected(*nodes, up:false, down:true)
163
- end
164
-
165
- #from a list of nodes, return all nodes that are not descendants of
166
- #other nodes in the graph
167
- def unneeded(*nodes)
168
- tokeep.merge(@nodes-nodes)
169
- nodes.each do |node|
170
- unneeded << node unless ancestors(node).any? {|c| tokeep.include?(c)}
171
- end
172
- end
173
- #return all dependencies that are not needed by any more nodes.
174
- #If some dependencies should be kept (think manual install), add them
175
- #to the unneeded parameter
176
- def unneeded_descendants(*nodes, needed:[])
177
- needed-=nodes #nodes to delete are in priority
178
- deps=descendants(*nodes)
179
- deps-=needed #but for children nodes, needed nodes are in priority
180
- unneeded(*deps)
181
- end
182
- #So to implement the equivalent of pacman -Rc packages
183
- #it suffices to add the ancestors of packages
184
- #For pacman -Rs, this is exactly unneeded_descendants
185
- #and pacman -Rcs would be ancestors(unneeded_descendants)
186
- #finally to clean all unneeded packages (provided we have a list of
187
- #packages 'tokeep' to keep), either use unneeded(@nodes-tokeep)
188
- #or unneeded_descendants(roots, needed:tokeep)
189
-
190
- #return the subgraph containing all the nodes passed as parameters,
191
- #and the complementary graph. The union of both may not be the full
192
- #graph [edges] in case the components are not connected
193
- def subgraph(*nodes)
194
- subgraph=Graph.new()
195
- compgraph=Graph.new()
196
- @nodes.each do |node|
197
- if nodes.include?(node)
198
- n=subgraph.build(node.name)
199
- node.children.each do |c|
200
- n.add_child(c) if nodes.include?(c)
201
- end
202
- else
203
- n=compgraph.build(node.name)
204
- node.children.each do |c|
205
- n.add_child(c) unless nodes.include?(c)
206
- end
207
- end
208
- end
209
- return subgraph, compgraph
210
- end
211
-
212
- end
213
- end