depression 0.0.1

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/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ group :development do
6
+ gem "awesome_print"
7
+ end
@@ -0,0 +1,22 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ depression (0.0.1)
5
+
6
+ GEM
7
+ remote: http://rubygems.org/
8
+ specs:
9
+ awesome_print (0.3.1)
10
+ mocha (0.9.9)
11
+ rake
12
+ rake (0.8.7)
13
+ test-unit (2.1.1)
14
+
15
+ PLATFORMS
16
+ ruby
17
+
18
+ DEPENDENCIES
19
+ awesome_print
20
+ depression!
21
+ mocha
22
+ test-unit
@@ -0,0 +1,7 @@
1
+ = Easy resolution of before/after relations for Ruby
2
+
3
+ == Todo
4
+
5
+ * Drop greedy relations if they conflict with simple relations.
6
+ * Implement a "friendly" mode that doesn't raise errors but simply drops
7
+ "older" relations until a circular relation is resolved.
@@ -0,0 +1,10 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ task :default => :test
5
+
6
+ require "rake/testtask"
7
+ Rake::TestTask.new do |t|
8
+ t.libs = ["lib"]
9
+ t.test_files = FileList["test/*_test.rb"]
10
+ end
@@ -0,0 +1,27 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "depression/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "depression"
7
+ s.version = Depression::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Lars Gierth"]
10
+ s.email = ["lars.gierth@gmail.com"]
11
+ s.homepage = "http://rubygems.org/gems/depression"
12
+ s.summary = %q{Easy resolution of before/after relations for Ruby}
13
+ s.description = %q{depression resolves before/after relations ny forming a
14
+ graph of them and flattening it. Simple before/after
15
+ relations are supported as well as "greedy" relations
16
+ (before/after all other items) with simple relations being
17
+ more important in the case of a conflict. Circular
18
+ dependencies are detected and cause an exception.}
19
+
20
+ s.add_development_dependency "test-unit"
21
+ s.add_development_dependency "mocha"
22
+
23
+ s.files = `git ls-files`.split("\n") - [".gitignore", ".rvmrc"]
24
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
25
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
26
+ s.require_paths = ["lib"]
27
+ end
@@ -0,0 +1,90 @@
1
+ class Depression
2
+ def self.process(items)
3
+ graph = new(items)
4
+ graph.process
5
+ graph.result
6
+ end
7
+
8
+ attr_reader :items, :result
9
+
10
+ def initialize(items)
11
+ @items, @result, @changed = items, [], false
12
+ end
13
+
14
+ def process
15
+ items.each do |item|
16
+ unless item.respond_to?(:name) && item.name
17
+ raise "Items need to have a name."
18
+ end
19
+ end
20
+
21
+ @data = Hash[*items.map do |item|
22
+ [item.name, Data.new(0, [])]
23
+ end.flatten]
24
+
25
+ build_dependencies
26
+
27
+ @data.each do |name, data|
28
+ increment(name) unless data.relations.empty?
29
+ data.relations.each do |rel|
30
+ increment(rel.name) if @data[rel.name].weight <= data.weight
31
+ end
32
+ end
33
+
34
+ @result = items.sort do |item, other|
35
+ @data[item.name].weight.<=>(@data[other.name].weight)
36
+ end
37
+ end
38
+
39
+ protected
40
+
41
+ def increment(name)
42
+ @stack ||= []
43
+ raise "Circular dep: #{@stack.inspect}" if @stack.include?(name)
44
+
45
+ @stack.push(name)
46
+
47
+ @data[name].weight += 1
48
+ @data[name].relations.each {|dep| increment(dep.name) }
49
+
50
+ @stack.delete(name)
51
+ end
52
+
53
+ def build_dependencies
54
+ items.each do |item|
55
+ data = @data[item.name]
56
+
57
+ item.relations[:before] ||= []
58
+ if item.relations[:before] == :all
59
+ rels = items.map do |item2|
60
+ next if item.name == item2.name
61
+ Relation.new(item2.name, :greedy_reverse)
62
+ end
63
+ rels.delete(nil)
64
+ data.relations.push(*deps)
65
+ else
66
+ item.relations[:before].each do |name|
67
+ next unless @data[name]
68
+ data.relations << Relation.new(name, :normal_reverse)
69
+ end
70
+ end
71
+
72
+ item.relations[:after] ||= []
73
+ if item.relations[:after] == :all
74
+ @data.each do |name, data2|
75
+ next if item.name == name
76
+ data2.relations << Relation.new(item.name, :greedy)
77
+ end
78
+ else
79
+ item.relations[:after].each do |name|
80
+ next unless @data[name]
81
+ @data[name].relations << Relation.new(item.name, :normal)
82
+ end
83
+ end
84
+ end
85
+ end
86
+
87
+ class Data < Struct.new(:weight, :relations); end
88
+
89
+ class Relation < Struct.new(:name, :type); end
90
+ end
@@ -0,0 +1,3 @@
1
+ class Depression
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,82 @@
1
+ require File.dirname(__FILE__) + "/helper.rb"
2
+
3
+ class DepressionTest < Test::Unit::TestCase
4
+ def setup
5
+ @item = Proc.new do |n, r|
6
+ r ||= {}
7
+ Struct.new(:name, :relations).new(n, r)
8
+ end
9
+ end
10
+
11
+ test "has items" do
12
+ items = [@item.call(:foo), @item.call(:bar)]
13
+ graph = Depression.new(items)
14
+ assert_equal items, graph.items
15
+
16
+ assert_raise(NoMethodError) { graph.items = [] }
17
+ end
18
+
19
+ test "expects items to have a name" do
20
+ assert_raise(RuntimeError) { Depression.new([:foo]).process }
21
+
22
+ Depression.new([@item.call(:foo)]).process
23
+ end
24
+
25
+ test "provides a shorthand method for processing items" do
26
+ items = [@item.call(:foo)]
27
+
28
+ instance = stub("instance")
29
+ Depression.expects(:new).with(items).returns(instance)
30
+ instance.expects(:process)
31
+ instance.expects(:result)
32
+
33
+ Depression.process(items)
34
+ end
35
+
36
+ test "resolves simple before/after relations" do
37
+ items = [
38
+ @item.call(:foo, :before => [:baz]),
39
+ @item.call(:bar, :after => [:foo]),
40
+ @item.call(:baz, :after => [:bar]),
41
+ @item.call(:asd, :before => [:foo]),
42
+ @item.call(:sdf, :before => [:foo, :baz], :after => [:asd])
43
+ ]
44
+
45
+ result = Depression.process(items).map {|i| i.name }
46
+ assert_equal [:asd, :sdf, :foo, :bar, :baz], result
47
+ end
48
+
49
+ test "resolves greedy before/after relations" do
50
+ items = [
51
+ @item.call(:foo, :before => [:bar]),
52
+ @item.call(:bar, :after => [:all]),
53
+ @item.call(:baz, :before => [:all])
54
+ ]
55
+
56
+ result = Depression.process(items).map {|i| i.name }
57
+ assert_equal [:baz, :foo, :bar], result
58
+ end
59
+
60
+ test "detects circular relations" do
61
+ items = [
62
+ @item.call(:foo, :before => [:bar]),
63
+ @item.call(:bar, :before => [:baz]),
64
+ @item.call(:baz, :before => [:asd]),
65
+ @item.call(:asd, :before => [:foo])
66
+ ]
67
+
68
+ begin
69
+ Depression.process(items)
70
+ rescue => e
71
+ end
72
+ assert e.message =~ /^Circular dep:/
73
+ end
74
+
75
+ test "drops greedy relations in favor of simple relations" do
76
+ pend("Not yet implemented.")
77
+ end
78
+
79
+ test "can drop 'older' relations until a circular relation is resolved" do
80
+ pend("Not yet implemented.")
81
+ end
82
+ end
@@ -0,0 +1,9 @@
1
+ require "rubygems"
2
+ require "bundler"
3
+ Bundler.setup(:default, :development)
4
+
5
+ require "test/unit"
6
+ require "mocha"
7
+ require "awesome_print"
8
+
9
+ require "depression"
metadata ADDED
@@ -0,0 +1,109 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: depression
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Lars Gierth
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-11-17 00:00:00 +01:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: test-unit
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :development
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: mocha
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 3
44
+ segments:
45
+ - 0
46
+ version: "0"
47
+ type: :development
48
+ version_requirements: *id002
49
+ description: |-
50
+ depression resolves before/after relations ny forming a
51
+ graph of them and flattening it. Simple before/after
52
+ relations are supported as well as "greedy" relations
53
+ (before/after all other items) with simple relations being
54
+ more important in the case of a conflict. Circular
55
+ dependencies are detected and cause an exception.
56
+ email:
57
+ - lars.gierth@gmail.com
58
+ executables: []
59
+
60
+ extensions: []
61
+
62
+ extra_rdoc_files: []
63
+
64
+ files:
65
+ - Gemfile
66
+ - Gemfile.lock
67
+ - README.rdoc
68
+ - Rakefile
69
+ - depression.gemspec
70
+ - lib/depression.rb
71
+ - lib/depression/version.rb
72
+ - test/depression_test.rb
73
+ - test/helper.rb
74
+ has_rdoc: true
75
+ homepage: http://rubygems.org/gems/depression
76
+ licenses: []
77
+
78
+ post_install_message:
79
+ rdoc_options: []
80
+
81
+ require_paths:
82
+ - lib
83
+ required_ruby_version: !ruby/object:Gem::Requirement
84
+ none: false
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ hash: 3
89
+ segments:
90
+ - 0
91
+ version: "0"
92
+ required_rubygems_version: !ruby/object:Gem::Requirement
93
+ none: false
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ hash: 3
98
+ segments:
99
+ - 0
100
+ version: "0"
101
+ requirements: []
102
+
103
+ rubyforge_project:
104
+ rubygems_version: 1.3.7
105
+ signing_key:
106
+ specification_version: 3
107
+ summary: Easy resolution of before/after relations for Ruby
108
+ test_files: []
109
+