grimoire 0.1.2 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 200bc22b954a33f6ec11d2a41403afafacc3fe35
4
- data.tar.gz: e2ebba16137affccdf764c24c08132f8668bc6ab
3
+ metadata.gz: 40a6acabedf3270488bbf3be2eba64330a819044
4
+ data.tar.gz: 0da4eaa00a46d7a6beb0d68452183e7557e55d04
5
5
  SHA512:
6
- metadata.gz: a4dbcf9162fe2846c739bb71fd1a9d50e87a7f843841663b0c7878917dbbf2dbab2a6ef004498543a3d07ba03c14806e714da846f15e523918c9f9fb434f5516
7
- data.tar.gz: fa8a7d53d999489bf596f3ffbf1f77d5fd04ee68b3b5e3e236aab6dc2df230f55d75f4100cca5e9a6e1d3c4d00c703e813052a1cf87cd64e5042d771be42aa9d
6
+ metadata.gz: e39fbd0a25f246552db87ecbc890288ab47107846485257e4e0e6bc8eed821388ac1e82dfa9416fe19a4e9a914c05e9019a7acaf2228f7a19da7274e7bc94817
7
+ data.tar.gz: 02d3a49f7df811b8a98a255e3234ae7ec47da17f9033b23d9a47f1e077bc2d9e40c2f4459e901a25c99769a0f90644311eee1d98e862b3608601e495f34d9efe
data/CHANGELOG.md CHANGED
@@ -1,3 +1,8 @@
1
+ # v0.1.4
2
+ * Provide simple system serialization support
3
+ * Fix dependency listing from units within path
4
+ * Allow checking existing path for constraint satisfaction
5
+
1
6
  # v0.1.2
2
7
  * Add JSON serialization support to utility instances
3
8
  * Add abstract for unit scoring
data/README.md CHANGED
@@ -1,5 +1,64 @@
1
1
  # Grimoire
2
2
 
3
+ Light weight generic dependency resolver. Supports weighted
4
+ solutions via scored units.
5
+
6
+ ## Usage
7
+
8
+ Basic usage flow:
9
+
10
+ * Create a system
11
+
12
+ ```ruby
13
+ system = Grimoire::System.new
14
+ ```
15
+
16
+ * Add units
17
+
18
+ ```ruby
19
+ system.add_units(
20
+ Grimoire::Unit.new(
21
+ :name => 'unit1',
22
+ :version => '1.0.0'
23
+ ),
24
+ Grimoire::Unit.new(
25
+ :name => 'unit1',
26
+ :version => '1.1.0'
27
+ ),
28
+ ...
29
+ )
30
+ ```
31
+
32
+ * Create a score keeper
33
+
34
+ _NOTE: Score keeper is optional and *must* be subclassed. This example will not actually work._
35
+
36
+ ```ruby
37
+ score_keeper = Grimoire::ScoreKeeper.new
38
+ ```
39
+
40
+ * Create solver
41
+
42
+ ```ruby
43
+ solver = Grimoire::Solver.new(
44
+ :system => system,
45
+ :score_keeper => score_keeper,
46
+ :requirements => [
47
+ ['unit1', '> 2.0.0'],
48
+ ['unit2', '> 1', '< 3']
49
+ ]
50
+ )
51
+ ```
52
+
53
+ * Generate solutions
54
+
55
+ ``ruby
56
+ solutions = solver.generate!
57
+ p solutions.pop
58
+ ```
59
+
60
+ The ideal solution will be the first path on the queue.
61
+
3
62
  ## Info
4
63
 
5
64
  * Repository: https://github.com/spox/grimoire
data/grimoire.gemspec CHANGED
@@ -11,6 +11,7 @@ Gem::Specification.new do |s|
11
11
  s.require_path = 'lib'
12
12
  s.license = 'Apache 2.0'
13
13
  s.add_runtime_dependency 'bogo', '~> 0.1.10'
14
+ s.add_runtime_dependency 'attribute_struct', '>= 0.1.12'
14
15
  s.add_development_dependency 'minitest'
15
16
  s.add_development_dependency 'pry'
16
17
  s.files = Dir['{lib}/**/**/*'] + %w(grimoire.gemspec README.md CHANGELOG.md CONTRIBUTING.md LICENSE)
data/lib/grimoire/path.rb CHANGED
@@ -6,8 +6,9 @@ module Grimoire
6
6
 
7
7
  attribute :units, Unit, :multiple => true, :default => []
8
8
 
9
+ # @return [Array<DEPENDENCY_CLASS>]
9
10
  def dependencies
10
- units.map(&:dependencies).flatten.uniq!
11
+ units.map(&:dependencies).flatten.uniq
11
12
  end
12
13
 
13
14
  end
@@ -1,3 +1,4 @@
1
+ require 'digest/sha2'
1
2
  require 'grimoire'
2
3
 
3
4
  module Grimoire
@@ -19,7 +20,9 @@ module Grimoire
19
20
  def initialize(*_)
20
21
  super
21
22
  @world = System.new
23
+ @log = []
22
24
  build_world(requirements.requirements, world, system)
25
+ @log.clear
23
26
  world.scrub!
24
27
  end
25
28
 
@@ -35,6 +38,9 @@ module Grimoire
35
38
  root = system unless root
36
39
  deps.each do |dep|
37
40
  units = root.subset(dep.name, dep.requirement)
41
+ sha = Digest::SHA256.hexdigest(MultiJson.dump(units))
42
+ next if @log.include?(sha)
43
+ @log.push(sha)
38
44
  units.each do |unit|
39
45
  build_world(unit.dependencies, my_world, root)
40
46
  end
@@ -118,8 +124,9 @@ module Grimoire
118
124
  #
119
125
  # @param dep [DEPENDENCY_CLASS]
120
126
  # @param given [DEPENDENCY_CLASS]
127
+ # @param current [Array<Unit>] current units within path
121
128
  # @return [Array<Unit>]
122
- def resolve(dep, given=nil)
129
+ def resolve(dep, given=nil, current=[])
123
130
  unit = given || unit_for(dep)
124
131
  if(unit.dependencies.empty?)
125
132
  [unit]
@@ -127,7 +134,7 @@ module Grimoire
127
134
  deps = [unit]
128
135
  begin
129
136
  unit.dependencies.map do |u_dep|
130
- existing = deps.detect{|d| d.name == u_dep.name}
137
+ existing = (current + deps).detect{|d| d.name == u_dep.name}
131
138
  if(existing)
132
139
  if(u_dep.requirement.satisfied_by?(existing.version))
133
140
  next
@@ -138,7 +145,7 @@ module Grimoire
138
145
  else
139
146
  reset_queue(u_dep.name) unless given
140
147
  end
141
- deps += resolve(u_dep)
148
+ deps += resolve(u_dep, nil, current + deps)
142
149
  deps.compact!
143
150
  u_dep
144
151
  end.compact.map do |u_dep| # validator
@@ -154,7 +161,7 @@ module Grimoire
154
161
  rescue Error::ResolutionPathInvalid
155
162
  retry
156
163
  end
157
- deps
164
+ deps.uniq
158
165
  end
159
166
  end
160
167
 
@@ -19,6 +19,9 @@ module Grimoire
19
19
  # @param unit [Unit]
20
20
  # @return [self]
21
21
  def add_unit(*unit)
22
+ if(bad_u = unit.flatten.detect{|u| !u.is_a?(Unit)})
23
+ raise TypeError.new "Expecting `Unit` instance but received `#{bad_u.class}`"
24
+ end
22
25
  [unit].flatten.compact.each do |u|
23
26
  unless(units[u.name])
24
27
  units[u.name] = []
@@ -34,8 +37,14 @@ module Grimoire
34
37
  # @param deps
35
38
  # @return [self]
36
39
  def remove_unit(unit)
40
+ unless(unit.is_a?(Unit))
41
+ raise TypeError.new "Expecting `Unit` instance but received `#{unit.class}`"
42
+ end
37
43
  if(units[unit.name])
38
44
  units[unit.name].delete(unit)
45
+ if(units[unit.name].empty?)
46
+ units.delete(unit.name)
47
+ end
39
48
  end
40
49
  self
41
50
  end
@@ -46,6 +55,9 @@ module Grimoire
46
55
  # @param constraint [REQUIREMENT_CLASS]
47
56
  # @return [Array<Unit>]
48
57
  def subset(unit_name, constraint)
58
+ unless(constraint.respond_to?(:requirements))
59
+ raise TypeError.new "Expecting `#{REQUIREMENT_CLASS}` but received `#{constraint.class}`"
60
+ end
49
61
  units[unit_name].find_all do |unit|
50
62
  constraint.satisfied_by?(unit.version)
51
63
  end
@@ -63,5 +75,13 @@ module Grimoire
63
75
  self
64
76
  end
65
77
 
78
+ # @return [String]
79
+ def to_json(*args)
80
+ MultiJson.dump(
81
+ Smash.new(:units => units),
82
+ *args
83
+ )
84
+ end
85
+
66
86
  end
67
87
  end
@@ -1,4 +1,4 @@
1
1
  module Grimoire
2
2
  # Current library version
3
- VERSION = Gem::Version.new('0.1.2')
3
+ VERSION = Gem::Version.new('0.1.4')
4
4
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: grimoire
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Roberts
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-03-06 00:00:00.000000000 Z
11
+ date: 2015-03-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bogo
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: 0.1.10
27
+ - !ruby/object:Gem::Dependency
28
+ name: attribute_struct
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 0.1.12
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 0.1.12
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: minitest
29
43
  requirement: !ruby/object:Gem::Requirement