drain 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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