alki 0.9.1 → 0.10.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 (43) hide show
  1. checksums.yaml +4 -4
  2. data/README.adoc +8 -88
  3. data/alki.gemspec +2 -2
  4. data/exe/alki +2 -1
  5. data/lib/alki/assembly/builder.rb +29 -23
  6. data/lib/alki/assembly/executor.rb +57 -31
  7. data/lib/alki/assembly/{handler_base.rb → handler.rb} +1 -1
  8. data/lib/alki/assembly/instance.rb +9 -2
  9. data/lib/alki/assembly/type.rb +19 -0
  10. data/lib/alki/assembly/types/assembly.rb +1 -0
  11. data/lib/alki/assembly/types/factory.rb +2 -2
  12. data/lib/alki/assembly/types/func.rb +2 -2
  13. data/lib/alki/assembly/types/group.rb +19 -3
  14. data/lib/alki/assembly/types/override.rb +0 -7
  15. data/lib/alki/assembly/types/proc_value.rb +2 -2
  16. data/lib/alki/assembly/types/service.rb +24 -13
  17. data/lib/alki/assembly.rb +7 -6
  18. data/lib/alki/dsls/assembly.rb +3 -4
  19. data/lib/alki/dsls/assembly_group.rb +47 -26
  20. data/lib/alki/dsls/assembly_type.rb +4 -14
  21. data/lib/alki/execution/context.rb +17 -20
  22. data/lib/alki/execution/context_class_builder.rb +16 -2
  23. data/lib/alki/execution/helpers.rb +29 -0
  24. data/lib/alki/execution/reference.rb +18 -0
  25. data/lib/alki/execution/value_helpers.rb +14 -0
  26. data/lib/alki/overlay_info.rb +1 -1
  27. data/lib/alki/override_builder.rb +3 -3
  28. data/lib/alki/version.rb +1 -1
  29. data/lib/alki_loader.rb +2 -0
  30. data/test/feature/alki_test.rb +3 -5
  31. data/test/feature/example_test.rb +1 -4
  32. data/test/feature/overlays_test.rb +34 -0
  33. data/test/feature/pseudo_elements_test.rb +1 -1
  34. data/test/feature/reference_overlays_test.rb +24 -0
  35. data/test/feature/tags_test.rb +77 -0
  36. data/test/feature_test_helper.rb +34 -0
  37. data/test/integration/dsls/assembly_test.rb +2 -2
  38. data/test/integration/dsls/assembly_type_test.rb +1 -1
  39. data/test/integration/dsls/service_dsl_test.rb +1 -1
  40. metadata +16 -16
  41. data/config/dsls.rb +0 -4
  42. data/lib/alki/execution/value_context.rb +0 -23
  43. data/lib/alki/reloadable_delegator.rb +0 -17
@@ -5,15 +5,14 @@ Alki do
5
5
  finish do
6
6
  add :config_dir, build(:value, ctx[:config_dir])
7
7
  add :assembly_name, build(:value, ctx[:assembly_name])
8
- prefix_overlays :original, ctx[:overlays]
9
8
 
10
9
  root = ctx[:root]
11
- overlays = ctx[:overlays]
10
+ meta = ctx[:meta]
12
11
  add_class_method :root do
13
12
  root
14
13
  end
15
- add_class_method :overlays do
16
- overlays
14
+ add_class_method :meta do
15
+ meta
17
16
  end
18
17
  end
19
18
  end
@@ -3,31 +3,52 @@ require 'alki/support'
3
3
  require 'alki/overlay_info'
4
4
 
5
5
  Alki do
6
- require_dsl 'alki/dsls/dsl'
7
-
8
6
  init do
9
7
  ctx[:root] = build(:group,{})
10
- ctx[:overlays] = []
8
+ ctx[:meta] = []
11
9
  end
12
10
 
13
11
  helper :add do |name,elem|
12
+ if @tags
13
+ ctx[:meta] << [[name.to_sym],:tags,@tags]
14
+ @tags = nil
15
+ end
14
16
  ctx[:root].children[name.to_sym] = elem
15
17
  nil
16
18
  end
17
19
 
18
20
  helper :build do |type,*args|
19
- Alki::Support.load_class("alki/assembly/types/#{type}").new *args
21
+ Alki.load("alki/assembly/types/#{type}").new *args
20
22
  end
21
23
 
22
- helper :prefix_overlays do |*prefix,overlays|
23
- overlays.each do |overlay|
24
- overlay[0].unshift *prefix
24
+ dsl_method :add_overlay do |type,target,overlay,args|
25
+ (ctx[:meta]||=[]) << [
26
+ [], :overlay,
27
+ Alki::OverlayInfo.new(
28
+ type,
29
+ target.to_s.split('.').map(&:to_sym),
30
+ overlay.to_s.split('.').map(&:to_sym),
31
+ args
32
+ )
33
+ ]
34
+ end
35
+
36
+ helper :prefix_meta do |*prefix,meta|
37
+ meta.each do |data|
38
+ data[0].unshift *prefix.map(&:to_sym)
25
39
  end
26
- overlays
40
+ meta
41
+ end
42
+
43
+ helper :update_meta do |*prefix,meta|
44
+ ctx[:meta].push *prefix_meta(*prefix,meta)
27
45
  end
28
46
 
29
- helper :update_overlays do |*prefix,overlays|
30
- ctx[:overlays].push *prefix_overlays(*prefix,overlays)
47
+ dsl_method :tag do |*tags|
48
+ unless tags.all?{|t| t.is_a? Symbol }
49
+ raise "Tags must be symbols"
50
+ end
51
+ @tags = tags
31
52
  end
32
53
 
33
54
  dsl_method :config_dir do
@@ -57,36 +78,36 @@ Alki do
57
78
  dsl_method :group do |name,&blk|
58
79
  grp = Alki::Dsls::AssemblyGroup.build(&blk)
59
80
  add name, grp[:root]
60
- update_overlays name, grp[:overlays]
81
+ update_meta name, grp[:meta]
61
82
  end
62
83
 
63
84
  dsl_method :load do |group_name,name=group_name.to_s|
64
- grp = Alki::Dsl.load(File.expand_path(name+'.rb',ctx[:config_dir]))[:class]
85
+ unless ctx[:prefix]
86
+ raise "Load command is not available without a config directory"
87
+ end
88
+ grp = Alki.load(File.join(ctx[:prefix],name))
65
89
  add name, grp.root
66
- update_overlays name, grp.overlays
90
+ update_meta name, grp.meta
67
91
  end
68
92
 
69
93
  dsl_method :mount do |name,pkg=name.to_s,**overrides,&blk|
70
- klass = Alki::Support.load_class pkg
71
- mounted_assemblies = klass.overlays.map do |(path,info)|
72
- [path.dup,info]
94
+ klass = Alki.load pkg
95
+ mounted_meta = klass.meta.map do |(path,type,info)|
96
+ [path.dup,type,info]
73
97
  end
74
- update_overlays name, mounted_assemblies
98
+ update_meta name, mounted_meta
75
99
 
76
100
  overrides = Alki::OverrideBuilder.build overrides, &blk
77
- update_overlays name, overrides[:overlays]
101
+ update_meta name, overrides[:meta]
78
102
 
79
103
  add name, build(:assembly, klass.root, overrides[:root])
80
104
  end
81
105
 
106
+ dsl_method :reference_overlay do |target,overlay,*args|
107
+ add_overlay :reference, target, overlay, args
108
+ end
109
+
82
110
  dsl_method :overlay do |target,overlay,*args|
83
- (ctx[:overlays]||=[]) << [
84
- [],
85
- Alki::OverlayInfo.new(
86
- target.to_s.split('.').map(&:to_sym),
87
- overlay.to_s.split('.').map(&:to_sym),
88
- args
89
- )
90
- ]
111
+ add_overlay :value, target, overlay, args
91
112
  end
92
113
  end
@@ -1,22 +1,12 @@
1
- require 'alki/assembly/handler_base'
1
+ require 'alki/assembly/type'
2
+ require 'alki/assembly/handler'
2
3
 
3
4
  Alki do
4
5
  require_dsl 'alki/dsls/class'
5
6
 
6
7
  init do
7
- set_super_class Alki::Assembly::HandlerBase, subclass: 'Handler'
8
-
9
- add_method :handler, private: true do |*args|
10
- self.class::Handler.new(self,*args)
11
- end
12
-
13
- add_method :index do |*args|
14
- handler(*args).index
15
- end
16
-
17
- add_method :output do |*args|
18
- handler(*args).output
19
- end
8
+ set_super_class Alki::Assembly::Handler, subclass: 'Handler'
9
+ set_super_class Alki::Assembly::Type
20
10
 
21
11
  # Add defined methods to handler class
22
12
  class_builder('Handler')[:module] = class_builder[:module]
@@ -1,28 +1,25 @@
1
- require 'alki/service_delegator'
2
-
1
+ require 'alki/execution/reference'
3
2
  module Alki
4
3
  module Execution
5
- module Context
6
- def lookup(*path)
7
- path.flatten.inject(self) do |group,elem|
8
- unless elem.is_a?(String) or elem.is_a?(Symbol)
9
- raise ArgumentError.new("lookup can only take Strings or Symbols")
10
- end
11
- elem.to_s.split('.').inject(group) do |group,name|
12
- raise "Invalid lookup elem" unless group.is_a? Context
13
- group.send name.to_sym
14
- end
15
- end
4
+ class Context
5
+ def initialize(executor,meta)
6
+ @__executor__ = executor
7
+ @__meta__ = meta
8
+ end
9
+
10
+ private
11
+
12
+ def __reference__(path,args,blk)
13
+ Reference.new(@__executor__,@__meta__,path,args,blk)
16
14
  end
17
15
 
18
- def lazy(*path)
19
- path = path.flatten.inject('') do |path,elem|
20
- unless elem.is_a?(String) or elem.is_a?(Symbol)
21
- raise ArgumentError.new("lookup can only take Strings or Symbols")
22
- end
23
- path << elem.to_s
16
+ def __execute__(path,args,blk)
17
+ ref = __reference__ path, args, blk
18
+ if respond_to?(:__process_reference__,true)
19
+ __process_reference__ ref
20
+ else
21
+ ref.call
24
22
  end
25
- Alki::ServiceDelegator.new self, path
26
23
  end
27
24
  end
28
25
  end
@@ -1,4 +1,5 @@
1
1
  require 'alki/class_builder'
2
+ require 'alki/execution/context'
2
3
 
3
4
  module Alki
4
5
  module Execution
@@ -15,9 +16,22 @@ module Alki
15
16
  (config[:scope]||{}).each do |name,path|
16
17
  methods[name] = {
17
18
  body:->(*args,&blk) {
18
- @__executor__.execute @__meta__, path, args, blk
19
+ __execute__ path, args, blk
19
20
  }
20
21
  }
22
+
23
+ methods[:"__raw_#{name}__"] = {
24
+ body:->(*args,&blk) {
25
+ @__executor__.execute @__meta__, path, args, blk
26
+ },
27
+ private: true
28
+ }
29
+
30
+ methods[:"__reference_#{name}__"] = {
31
+ body:->(*args,&blk) {
32
+ __reference__ path, args, blk
33
+ },
34
+ }
21
35
  end
22
36
  (config[:methods]||{}).each do |name,body|
23
37
  methods[name] = {
@@ -26,7 +40,7 @@ module Alki
26
40
  }
27
41
  end
28
42
  ClassBuilder.build(
29
- initialize_params: [:__executor__,:__meta__],
43
+ super_class: Alki::Execution::Context,
30
44
  modules: config[:modules],
31
45
  instance_methods: methods,
32
46
  )
@@ -0,0 +1,29 @@
1
+ require 'alki/service_delegator'
2
+
3
+ module Alki
4
+ module Execution
5
+ module Helpers
6
+ def lookup(*path)
7
+ path.flatten.inject(self) do |group,elem|
8
+ unless elem.is_a?(String) or elem.is_a?(Symbol)
9
+ raise ArgumentError.new("lookup can only take Strings or Symbols")
10
+ end
11
+ elem.to_s.split('.').inject(group) do |group,name|
12
+ raise "Invalid lookup elem" unless group.is_a? Helpers
13
+ group.send name.to_sym
14
+ end
15
+ end
16
+ end
17
+
18
+ def lazy(*path)
19
+ path = path.flatten.inject('') do |path,elem|
20
+ unless elem.is_a?(String) or elem.is_a?(Symbol)
21
+ raise ArgumentError.new("lookup can only take Strings or Symbols")
22
+ end
23
+ path << elem.to_s
24
+ end
25
+ Alki::ServiceDelegator.new self, path
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,18 @@
1
+ module Alki
2
+ module Execution
3
+ class Reference
4
+ attr_accessor :executor, :meta, :path, :args, :blk
5
+ def initialize(executor,meta,path,args,blk)
6
+ @executor = executor
7
+ @meta = meta
8
+ @path = path
9
+ @args = args
10
+ @blk = blk
11
+ end
12
+
13
+ def call
14
+ @executor.execute @meta, @path, @args, @blk
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,14 @@
1
+ require 'alki/execution/helpers'
2
+ require 'alki/overlay_delegator'
3
+
4
+ module Alki
5
+ module Execution
6
+ module ValueHelpers
7
+ include Helpers
8
+
9
+ def delegate_overlay(obj,overlay,**args)
10
+ Alki::OverlayDelegator.new(obj,overlay,args)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -1,3 +1,3 @@
1
1
  module Alki
2
- OverlayInfo = Struct.new(:target,:overlay,:args)
2
+ OverlayInfo = Struct.new(:type,:target,:overlay,:args)
3
3
  end
@@ -6,9 +6,9 @@ module Alki
6
6
  if blk
7
7
  Alki::Dsls::AssemblyGroup.build(&blk)
8
8
  elsif override_hash && !override_hash.empty?
9
- { root: create_override_group(override_hash), overlays: [] }
9
+ { root: create_override_group(override_hash), meta: [] }
10
10
  else
11
- { root: nil, overlays: [] }
11
+ { root: nil, meta: [] }
12
12
  end
13
13
  end
14
14
 
@@ -30,7 +30,7 @@ module Alki
30
30
  end
31
31
 
32
32
  def self.build_type(type,*args)
33
- Alki::Support.load_class("alki/assembly/types/#{type}").new *args
33
+ Alki.load("alki/assembly/types/#{type}").new *args
34
34
  end
35
35
 
36
36
  end
data/lib/alki/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Alki
2
- VERSION = "0.9.1"
2
+ VERSION = "0.10.0"
3
3
  end
@@ -0,0 +1,2 @@
1
+ Alki::Loader.register 'alki/assembly/types', builder: 'alki/dsls/assembly_type'
2
+ Alki::Loader.register 'alki/dsls', builder: 'alki/dsls/dsl'
@@ -22,11 +22,12 @@ describe Alki do
22
22
  end
23
23
 
24
24
  it 'should load assembly definition from config_dir if provided' do
25
- build(config_dir: fixture_path('tlogger','config')).new.must_respond_to :log
25
+ build(name: 'tlogger', config_dir: fixture_path('tlogger','config')).new.must_respond_to :log
26
26
  end
27
27
 
28
28
  it 'should load file other than assembly if provided with primary_config' do
29
29
  build(
30
+ name: 'example',
30
31
  config_dir: fixture_path('example','config'),
31
32
  primary_config: 'settings'
32
33
  ).new.must_respond_to :fizz
@@ -35,16 +36,13 @@ describe Alki do
35
36
  it 'should create class if provided with a name' do
36
37
  klass = build(name: 'alki_test/test_assembly')
37
38
  AlkiTest::TestAssembly.must_equal klass
38
- Object.send :remove_const, :AlkiTest
39
+ undefine :AlkiTest
39
40
  end
40
41
 
41
42
  it 'should automatically determine config_dir and name if project_assembly provided' do
42
- was_defined = defined? Tlogger
43
- Object.send :remove_const, :Tlogger if was_defined
44
43
  klass = build(project_assembly: fixture_path('tlogger','lib','tlogger.rb'))
45
44
  Tlogger.must_equal klass
46
45
  klass.new.must_respond_to :log
47
- Object.send :remove_const, :Tlogger unless was_defined
48
46
  end
49
47
  end
50
48
 
@@ -1,7 +1,4 @@
1
- require 'alki/test'
2
-
3
- $LOAD_PATH.unshift Alki::Test.fixture_path('example','lib')
4
- $LOAD_PATH.unshift Alki::Test.fixture_path('tlogger','lib')
1
+ require 'alki/feature_test'
5
2
 
6
3
  describe 'Example' do
7
4
  before do
@@ -208,6 +208,40 @@ describe 'Overlays' do
208
208
  obj.mounted.svc1.must_equal :parent
209
209
  end
210
210
 
211
+ it 'should set overlays on overridden elements' do
212
+ child = Alki.create_assembly do
213
+ set :test_overlay, ->(value) {:"#{value}_child"}
214
+ overlay 'svc1', :test_overlay
215
+ service :svc1 do
216
+ :test1
217
+ end
218
+ end
219
+ assembly = Alki.create_assembly do
220
+ group :grp do
221
+ service :svc2 do
222
+ :test2
223
+ end
224
+ end
225
+ overlay 'grp.svc2', :test_overlay
226
+ set :test_overlay, ->(value) {:"#{value}_parent"}
227
+
228
+ mount :mounted, child do
229
+ service :svc1 do
230
+ :test12
231
+ end
232
+ end
233
+ end
234
+ obj = assembly.new do
235
+ group :grp do
236
+ service :svc2 do
237
+ :test22
238
+ end
239
+ end
240
+ end
241
+ obj.mounted.svc1.must_equal :test12_child
242
+ obj.grp.svc2.must_equal :test22_parent
243
+ end
244
+
211
245
  it 'should allow setting overlays on assembly_instance' do
212
246
  values = []
213
247
  mock = Minitest::Mock.new
@@ -22,7 +22,7 @@ describe 'Pseudo Elements' do
22
22
  mount :two, two
23
23
  set :num, 1
24
24
  end
25
- zero = Alki.create_assembly(config_dir: @config_dir) do
25
+ zero = Alki.create_assembly(name: 'alki_test', config_dir: @config_dir) do
26
26
  mount :one, one
27
27
  set :num, 0
28
28
  set :has_parent do
@@ -0,0 +1,24 @@
1
+ require 'alki/feature_test'
2
+
3
+ describe 'Reference Overlays' do
4
+ it 'should allow overlaying all references made by a service' do
5
+ assembly = Alki.create_assembly do
6
+ set :val, :val
7
+ service :svc_ref do
8
+ :svc
9
+ end
10
+ func :func do
11
+ :func
12
+ end
13
+ factory :fact do
14
+ -> val { val }
15
+ end
16
+ service :svc do
17
+ :"#{val}_#{svc_ref}_#{func}_#{fact(:f1)}_#{fact(:f2)}"
18
+ end
19
+ reference_overlay :svc, :overlay
20
+ set :overlay, -> ref { :"o#{ref.call}"}
21
+ end
22
+ assembly.new.svc.must_equal :oval_osvc_ofunc_of1_of2
23
+ end
24
+ end
@@ -0,0 +1,77 @@
1
+ require 'alki/feature_test'
2
+
3
+ describe 'Tags' do
4
+ it 'should allow setting overlays via tags' do
5
+ assembly = Alki.create_assembly do
6
+ tag :tag1, :tag2
7
+ service :svc1 do
8
+ :svc1
9
+ end
10
+
11
+ tag :tag1
12
+ service :svc2 do
13
+ :svc2
14
+ end
15
+
16
+ overlay '%tag1', :overlay1
17
+ overlay '%tag2', :overlay2
18
+
19
+ set :overlay1, -> val { :"one_#{val}"}
20
+ set :overlay2, -> val { :"two_#{val}"}
21
+ end
22
+ obj = assembly.new
23
+
24
+ obj.svc1.must_equal :two_one_svc1
25
+ obj.svc2.must_equal :one_svc2
26
+ end
27
+
28
+ it 'should apply to all elements in groups' do
29
+ assembly = Alki.create_assembly do
30
+ tag :tag1
31
+ group :grp do
32
+ service :svc1 do
33
+ :svc1
34
+ end
35
+
36
+ service :svc2 do
37
+ :svc2
38
+ end
39
+ end
40
+
41
+ overlay '%tag1', :overlay1
42
+ set :overlay1, -> val { :"one_#{val}"}
43
+ end
44
+ obj = assembly.new
45
+
46
+ obj.grp.svc1.must_equal :one_svc1
47
+ obj.grp.svc2.must_equal :one_svc2
48
+ end
49
+
50
+ it 'should be accessible through mounts' do
51
+ child = Alki.create_assembly do
52
+ tag :tag1
53
+ service :svc1 do
54
+ :svc1
55
+ end
56
+
57
+ overlay '%tag2', :overlay
58
+ set :overlay, -> val { :"child_#{val}"}
59
+ end
60
+
61
+ assembly = Alki.create_assembly do
62
+ mount :child, child
63
+
64
+ tag :tag2
65
+ service :svc2 do
66
+ :svc2
67
+ end
68
+
69
+ overlay '%tag1', :overlay
70
+ set :overlay, -> val { :"parent_#{val}"}
71
+ end
72
+ obj = assembly.new
73
+
74
+ obj.svc2.must_equal :child_svc2
75
+ obj.child.svc1.must_equal :parent_svc1
76
+ end
77
+ end
@@ -1 +1,35 @@
1
1
  require 'alki'
2
+
3
+
4
+ class Minitest::Spec
5
+ before do
6
+ @test_projects = [
7
+ Alki::Test.fixture_path('example'),
8
+ Alki::Test.fixture_path('tlogger')
9
+ ]
10
+ @test_projects.each do |proj|
11
+ $LOAD_PATH.unshift File.join(proj,'lib')
12
+ end
13
+ end
14
+
15
+ after do
16
+ $LOADED_FEATURES.delete_if do |p|
17
+ @test_projects.any? do |proj|
18
+ p.start_with?(File.join(proj,''))
19
+ end
20
+ end
21
+ $LOAD_PATH.delete_if do |p|
22
+ @test_projects.any? do |proj|
23
+ p.start_with?(File.join(proj,''))
24
+ end
25
+ end
26
+ undefine :Example, false
27
+ undefine :Tlogger, false
28
+ end
29
+
30
+ def undefine(sym,force=true)
31
+ if force || Object.const_defined?(sym)
32
+ Object.send :remove_const, sym
33
+ end
34
+ end
35
+ end
@@ -14,7 +14,7 @@ describe Alki::Dsls::Assembly do
14
14
  end
15
15
  end
16
16
  end
17
- res[:class].root.children[:test].must_respond_to :block
18
- res[:class].root.children[:group1].children[:test2].must_respond_to :block
17
+ res.root.children[:test].must_respond_to :block
18
+ res.root.children[:group1].children[:test2].must_respond_to :block
19
19
  end
20
20
  end
@@ -3,7 +3,7 @@ require 'alki/dsls/assembly_type'
3
3
 
4
4
  describe Alki::Dsls::AssemblyType do
5
5
  def build(&blk)
6
- @klass = Alki::Dsls::AssemblyType.build(&blk)[:class]
6
+ @klass = Alki::Dsls::AssemblyType.build(&blk)
7
7
  end
8
8
 
9
9
  def klass
@@ -3,7 +3,7 @@ require 'alki/dsls/service'
3
3
 
4
4
  describe Alki::Dsls::Service do
5
5
  def build(&blk)
6
- @c = Alki::Dsls::Service.build(&blk)[:class]
6
+ @c = Alki::Dsls::Service.build(&blk)
7
7
  end
8
8
 
9
9
  describe :use do