grimoire 0.1.2 → 0.1.4

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 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