alki 0.9.1 → 0.10.0

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