potrubi 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,226 @@
1
+
2
+ # potrubi contract recipes
3
+
4
+ # to ease the creation of contracts, accessors, etc in class bodies
5
+
6
+ # These are *mixin* ('class') methods; not instance ones
7
+
8
+ # Uses conventions for names etc dedined by (in) contract mixin
9
+
10
+ require_relative '../bootstrap'
11
+
12
+ requireList = %w(contract util)
13
+ requireList.each {|r| require_relative "#{r}"}
14
+
15
+ mixinContent = Module.new do
16
+
17
+ include Potrubi::Bootstrap
18
+ include Potrubi::Mixin::Util
19
+
20
+ def standard_accessor_edit(k, v)
21
+ {ACCESSOR_NAME: k, ACCESSOR_CONTRACT: k}
22
+ end
23
+
24
+ def standard_mustbe_edit(k, v)
25
+ {MUSTBE_NAME: k, MUSTBE_SPEC: k}
26
+ end
27
+
28
+ # convenience methods
29
+
30
+ def merge_edits(*edits)
31
+ Potrubi::Mixin::Dynamic.dynamic_merge_edits(*edits)
32
+ end
33
+
34
+ def merge_specs(*specs)
35
+ specs.flatten
36
+ end
37
+
38
+ def merge_spec_and_edit(spec, edit)
39
+ { edit: edit, spec: spec}
40
+ end
41
+
42
+ # This method is peculair to accessors & mustbes
43
+ # not general purpose as e.g. hash treatment makes assumptions
44
+
45
+ def standard_case_statement(k, v, s, edit, spec)
46
+ eye = :'rcp_std_case'
47
+ r = case v
48
+ when Symbol then merge_spec_and_edit(spec, merge_edits(edit, {IS_VALUE_TEST: "testValue.is_a?(#{v.to_s.capitalize})"}))
49
+ when Class, String then merge_spec_and_edit(spec, merge_edits(edit, {IS_VALUE_TEST: "testValue.is_a?(#{v})"}))
50
+ when NilClass then merge_spec_and_edit(spec, merge_edits(edit, {IS_VALUE_TEST: 'testValue'}))
51
+ when Array then v # dynamic_define_methods will parse
52
+ when Proc then
53
+ [ merge_spec_and_edit(spec, merge_edits(edit, {IS_VALUE_TEST: 'false'})), # error on default isValueText
54
+ {name: "is_value_#{k}?", spec: v}, # ... but override is_value method
55
+ ]
56
+ when Hash then merge_spec_and_edit(merge_specs([spec, v[:spec]]), merge_edits(edit, {IS_VALUE_TEST: 'false'}, v[:edit]))
57
+ else
58
+ potrubi_bootstrap_surprise_exception(v, eye, "accessor name >#{k}< spec not expected")
59
+ end
60
+ $DEBUG_POTRUBI_BOOTSTRAP && potrubi_bootstrap_logger_ca(eye, potrubi_bootstrap_logger_fmt_who(k: k, v: v, edit: edit), potrubi_bootstrap_logger_fmt_who(spec: spec), potrubi_bootstrap_logger_fmt_who(r: r))
61
+ r
62
+ #STOPCASEEXIT
63
+ end
64
+
65
+ def standard_accessor_recipe_block(s) # returns a lambda
66
+ ->(k, v) {
67
+ edit = standard_accessor_edit(k, v)
68
+ ###spec = {spec: s}
69
+ spec = s
70
+ r = standard_case_statement(k, v, s, edit, spec)
71
+ #puts("\n\n\nACCE RCP BLOK r >#{r}<\n\n\n")
72
+ r
73
+ #STOPACCEBLOK
74
+ }
75
+ end
76
+
77
+ def standard_mustbe_recipe_block(s) # returns a lambda
78
+ ->(k, v) {
79
+ edit = standard_mustbe_edit(k, v)
80
+ ###spec = {spec: s}
81
+ spec = s
82
+ r = standard_case_statement(k, v, s, edit, spec)
83
+ #puts("\n\n\nMUSTBE RCP BLOK r >#{r}<")
84
+ r
85
+ }
86
+ end
87
+
88
+
89
+ def resolve_recipe_texts(*recipeTexts)
90
+ eye = :'rslv_rcp_texts'
91
+
92
+ utilityText = Potrubi::Mixin::Contract::CONTRACT_TEXTS
93
+
94
+ resolvedTexts = recipeTexts.flatten.map do | recipeText |
95
+ puts("recipeText >#{recipeText.class}< >#{recipeText}<")
96
+ case recipeText
97
+ when Symbol then utilityText[recipeText]
98
+ when Proc then recipeText
99
+ else
100
+ potrubi_bootstrap_surprise_exception(recipeText, eye, "recipeText is what?")
101
+ ###recipeText
102
+ end
103
+ end
104
+
105
+ resolvedTexts
106
+
107
+ end
108
+ def resolve_recipe_texts(*recipeTexts)
109
+ recipeTexts.flatten
110
+ end
111
+
112
+
113
+ def recipe_accessors(attrTarget, attrDefs, *attrTexts, &attrBlok)
114
+ eye = :'rcp_accessors'
115
+
116
+ ###STOPHEREACCS
117
+
118
+ #puts("K0")
119
+
120
+ $DEBUG_POTRUBI_BOOTSTRAP && potrubi_bootstrap_logger_me(eye, potrubi_bootstrap_logger_fmt_who(attrTarget: attrTarget, attrDefs: attrDefs, attrTexts: attrTexts))
121
+
122
+ #puts("K1")
123
+
124
+ #textDefs = resolve_recipe_texts(attrTexts)
125
+ textDefs = resolve_recipe_texts(attrTexts.empty? ? :package_accessor_with_contract : attrTexts) # default is contract accessor
126
+
127
+ #puts("TEXT DEFS >#{textDefs.class}< >#{textDefs}<")
128
+
129
+ procBlok = Kernel.block_given? ? attrBlok : standard_accessor_recipe_block(textDefs)
130
+
131
+ Potrubi::Mixin::Dynamic.dynamic_define_methods(attrTarget, attrDefs, &procBlok)
132
+
133
+ $DEBUG_POTRUBI_BOOTSTRAP && potrubi_bootstrap_logger_mx(eye, potrubi_bootstrap_logger_fmt_who(attrTarget: attrTarget, attrDefs: attrDefs, attrTexts: attrTexts))
134
+
135
+ self
136
+
137
+ ##STOPHEREACCSEXIT
138
+ end
139
+
140
+ def recipe_mustbes(attrTarget, attrDefs, *attrTexts, &attrBlok)
141
+ eye = :'rcp_mustbes'
142
+
143
+ $DEBUG_POTRUBI_BOOTSTRAP && potrubi_bootstrap_logger_me(eye, potrubi_bootstrap_logger_fmt_who(attrTarget: attrTarget, attrDefs: attrDefs, attrTexts: attrTexts))
144
+
145
+ textDefs = resolve_recipe_texts(attrTexts.empty? ? :package_mustbe : attrTexts) # default is standard mustbe
146
+
147
+ procBlok = Kernel.block_given? ? attrBlok : standard_mustbe_recipe_block(textDefs)
148
+
149
+ Potrubi::Mixin::Dynamic.dynamic_define_methods(attrTarget, attrDefs, &procBlok)
150
+
151
+ $DEBUG_POTRUBI_BOOTSTRAP && potrubi_bootstrap_logger_mx(eye, potrubi_bootstrap_logger_fmt_who(attrTarget: attrTarget, attrDefs: attrDefs, attrTexts: attrTexts))
152
+
153
+ self
154
+
155
+ end
156
+
157
+ end
158
+
159
+ module Potrubi
160
+ module Mixin
161
+ module ContractRecipes
162
+ end
163
+ end
164
+ end
165
+
166
+ Potrubi::Mixin::ContractRecipes.extend(mixinContent) # Make mixin methods
167
+
168
+ __END__
169
+
170
+ # quick tests
171
+
172
+ require '../core'
173
+
174
+ $DEBUG = true
175
+ $DEBUG_POTRUBI_BOOTSTRAP = true
176
+
177
+ testClass = Class.new do
178
+
179
+ include Potrubi::Core
180
+
181
+ attrAccessors = {
182
+ #jmx_user: :string,
183
+ #jmx_pass: :string,
184
+ #jmx_host: :string,
185
+ ###jmx_port: :string,
186
+ #jmx_port: :fixnum,
187
+ #jmx_connection: nil,
188
+ #jmx_connection: 'JMX::MBeanServerConnectionProxy',
189
+ #beans_attributes: :hash,
190
+ #beans_specifications: :hash,
191
+ #jmx_host: ->(h) {h.is_a?(String)},
192
+
193
+ #jmx_orts: {spec: 'def is_value_jmx_orts?(v); v.is_a?(String); end'},
194
+
195
+ #jmx_keys: {edit: {ACCESSOR_KEYS: 'self.class.accessor_keys'},
196
+ #spec: :method_accessor_is_value_and_keys}
197
+
198
+ jmx_users1: {edit: {KEY_TYPE: :string, VALUE_TYPE: :jmx_user}, spec: :method_accessor_is_value_typed_collection},
199
+ jmx_users2: {edit: {KEY_TYPE: :string, VALUE_TYPE: :jmx_user, VALUE_IS_NIL_RESULT: 'true', KEY_NAMES: [:a, :b, :c]}, spec: :method_accessor_is_value_typed_collection_with_keys}
200
+
201
+
202
+ }
203
+
204
+ attraccessorTexts = [:package_accessor_with_contract]
205
+
206
+ Potrubi::Mixin::ContractRecipes.recipe_accessors(self, attrAccessors, attraccessorTexts)
207
+
208
+
209
+ mustbeContracts = {
210
+ what1: :string,
211
+ what2: :hash,
212
+ what3: 'Riemann::Feed::Feeder'
213
+ }
214
+
215
+ #Potrubi::Mixin::ContractRecipes.recipe_mustbes(self, mustbeContracts)
216
+
217
+ end
218
+
219
+ testInst = testClass.new
220
+
221
+ #testInst.mustbe_jmx_host_or_croak('A string')
222
+ #testInst.mustbe_jmx_host_or_croak(:symbol)
223
+ #testInst.mustbe_jmx_orts_or_croak('A string')
224
+ #testInst.mustbe_jmx_orts_or_croak(:symbol)
225
+ __END__
226
+
@@ -0,0 +1,105 @@
1
+
2
+ # potrubi contract methods
3
+
4
+ require_relative '../bootstrap'
5
+ require_relative "dynamic"
6
+
7
+ #requireList = %w(dynamic)
8
+ #requireList.each {|r| require_relative "#{r}"}
9
+
10
+ #$DEBUG = true
11
+ #$DEBUG_POTRUBI_BOOTSTRAP = true
12
+
13
+ mixinContent = Module.new do
14
+
15
+ # mustbe contracts
16
+
17
+ mustbeDefaultSpec = [:package_mustbe]
18
+ mustbeLimited1OneArgSpec = [:method_mustbe_one_arg, :alias_is_value_value_is]
19
+ mustbeLimited2OneArgSpec = [mustbeLimited1OneArgSpec, :method_mustbe_key, :method_mustbe_one_arg_or_nil, :method_mustbe_collections].flatten
20
+ mustbeLimited1TwoArgSpec = [:method_mustbe_two_arg, :alias_is_value_value_is]
21
+
22
+ mustbeMethods = {
23
+ :hash => [:package_mustbe, :method_mustbe_hash_with_proc, :method_mustbe_one_arg_or_nil_with_proc].flatten,
24
+ #=begin
25
+ :array => [:package_mustbe, :method_mustbe_array_with_proc, :method_mustbe_one_arg_or_nil_with_proc, :method_mustbe_subset].flatten,
26
+ :string => nil,
27
+ :symbol => nil,
28
+ :fixnum => nil,
29
+ :range => nil,
30
+ :proc => nil,
31
+ :class => nil,
32
+ :module => nil,
33
+ :time => nil,
34
+ :enumerator => nil,
35
+ :regexp => nil,
36
+ :struct => nil,
37
+ :empty => [{:name => :'is_value_empty?', :spec => ->(c) {(c.respond_to?(:empty?) && c.empty?) ? c : nil }}, mustbeLimited1OneArgSpec].flatten,
38
+ :not_empty => [{:name => :'is_value_not_empty?', :spec => ->(c) {(c.respond_to?(:empty?) && (! c.empty?)) ? c : nil }}, mustbeLimited1OneArgSpec].flatten,
39
+ :not_nil => [{:name => :'is_value_not_nil?', :spec => ->(c) { c }}, mustbeLimited1OneArgSpec].flatten,
40
+ :file => [{:name => :'is_value_file?', :spec => ->(f) {(f.is_a?(String) && File.file?(f)) ? f : nil}}, mustbeLimited2OneArgSpec].flatten,
41
+ :directory => [{:name => :'is_value_directory?', :spec => ->(d) {(f.is_a?(String) && File.directory?(d)) ? d : nil}}, mustbeLimited2OneArgSpec].flatten,
42
+ :file_or_directory => [{:name => :'is_value_file_or_directory?', :spec => ->(e) {(e.is_a?(String) && (File.file?(e) || File.directory?(e))) ? e : nil}}, mustbeLimited2OneArgSpec].flatten,
43
+ :key => [{:name => :'is_value_key?', :spec => ->(h,k) {(h.respond_to?(:has_key?) && h.has_key?(k)) ? h[k] : nil}}, mustbeLimited1TwoArgSpec].flatten,
44
+ :not_key => [{:name => :'is_value_not_key?', :spec => ->(h,k) {is_value_key?(h,k) ? nil : k}}, mustbeLimited1TwoArgSpec].flatten,
45
+ :any => [{:name => :'is_value_any?', :spec => ->(v) {v} }].flatten,
46
+ :same_class => [{:name => :'is_value_same_class?', :spec => ->(p,q) {((r = p.class) == q.class) ? r : nil}}, mustbeLimited1TwoArgSpec].flatten,
47
+ :instance_of => [{:name => :'is_value_instance_of?', :spec => ->(p,q) {p.instance_of?(q) ? p : nil}}, mustbeLimited1TwoArgSpec].flatten,
48
+ #=end
49
+ }
50
+
51
+ mustbeSpecs = mustbeMethods.each_with_object({}) { | (mustbeName, mustbeSpec), h | h[mustbeName] = mustbeSpec || mustbeDefaultSpec }
52
+
53
+ Potrubi::Mixin::Dynamic::dynamic_define_methods(self, mustbeSpecs) do |k, v|
54
+ edits = {
55
+ ###:MUSTBE_TEST => k.to_s.capitalize,
56
+ IS_VALUE_TEST: "testValue.is_a?(#{k.to_s.capitalize})",
57
+ MUSTBE_NAME: k,
58
+ ###MUSTBE_SPEC: v,
59
+ }
60
+ case v
61
+ when Hash then v.merge({:edit => [edits, v[:edit]]})
62
+ else
63
+ {:edit => edits, :spec => v}
64
+ end
65
+ end
66
+
67
+
68
+ # Compare Contracts
69
+
70
+ compareMethods = {
71
+ :eq => '==',
72
+ :equal => '==',
73
+ :lt => '<',
74
+ :le => '<=',
75
+ :less_or_equal => '<=',
76
+ # :less_than_or_equal => '<=',
77
+ # :lessthan_or_equal => '<=',
78
+ :gt => '>',
79
+ :ge => '>=',
80
+ :greater_or_equal => '>=',
81
+ # :greater_than_or_equal => '>=',
82
+ # :greaterthan_or_equal => '>=',
83
+ :identical => '===',
84
+ :ne => '!=',
85
+ :not_equal => '!=',
86
+ # :lessequal => '<=',
87
+ }
88
+
89
+ Potrubi::Mixin::Dynamic::dynamic_define_methods(self, compareMethods) do | mN, mO |
90
+ # puts "<=> #{eye} mN >#{mN.class}< >#{mN}< mO >#{mO.class}< >#{mO}< textValue >#{textValue.class}< >\n#{textValue}\n<"
91
+ {edit: {MUSTBE_NAME: mN, MUSTBE_SPEC: mO}, spec: :method_mustbe_compare}
92
+ end
93
+
94
+ end
95
+
96
+ module Potrubi
97
+ module Mixin
98
+ module Contract
99
+ end
100
+ end
101
+ end
102
+
103
+ Potrubi::Mixin::Contract.__send__(:include, mixinContent) # Instance Methods
104
+
105
+ __END__
@@ -0,0 +1,100 @@
1
+
2
+ # potrubi mixin dynamic
3
+
4
+ # dynamic method, etc generation
5
+
6
+ require_relative '../bootstrap'
7
+ require_relative 'dynamic'
8
+
9
+ metaclassMethods = Module.new do
10
+
11
+ include Potrubi::Bootstrap
12
+ include Potrubi::Mixin::Dynamic
13
+
14
+ #=begin
15
+ def recipe_new(tgtMod, newSpecs, &block)
16
+ dynamic_define_methods(tgtMod, newSpecs) do | newName, newKlass |
17
+
18
+ edits = {
19
+ :et_new_name => newName.to_s.downcase,
20
+ :et_new_class => newKlass.to_s,
21
+ :et_new_eyecatcher => "new_#{newName}".downcase,
22
+ }
23
+
24
+ newText = <<-'ENDOFMETHOD'
25
+ def new_et_new_name_or_croak(*a, &b)
26
+ r = et_new_class.new(*a, &b)
27
+ logger_ca(:et_new_eyecatcher, logger_fmt_who(:'et_new_name' => r))
28
+ r
29
+ end
30
+ ENDOFMETHOD
31
+
32
+ {:edit => edits, :spec => newText}
33
+
34
+ end
35
+ end
36
+ #=end
37
+ #=begin
38
+ def recipe_rescue_croak(tgtMod, croakSpecs, &block)
39
+ dynamic_define_methods(tgtMod, croakSpecs) { | rescueName, rescueValue | "def #{rescueName}(*a, &b); #{rescueName}_or_croak(*a, &b) rescue #{rescueValue || 'nil'}; end\n" }
40
+ end
41
+ #=end
42
+
43
+ #=begin
44
+ def recipe_aliases(tgtMod, aliasSpecs, &block)
45
+ dynamic_define_methods(tgtMod, aliasSpecs) { | aliasName, realName | "alias_method :'#{aliasName}', :'#{realName}';\n" }
46
+ end
47
+ #=end
48
+
49
+ #=begin
50
+ def recipe_croak_rescue(targetModule, croakArgs={}, &croakBlok)
51
+ eye = :rcp_crk_rsc
52
+
53
+ $DEBUG_POTRUBI_BOOTSTRAP && potrubi_bootstrap_logger_me(eye, "targetModule >#{targetModule.class}< >#{targetModule}< croakArgs >#{croakArgs}<")
54
+
55
+ potrubi_bootstrap_mustbe_module_or_croak(targetModule, eye)
56
+
57
+ knownMethods = targetModule.instance_methods.map(&:to_s)
58
+
59
+ includeMethods = (r = croakArgs[:include]) ? [r].flatten.compact.uniq.map(&:to_s) : knownMethods
60
+ excludeMethods = (r = croakArgs[:exclude]) ? [r].flatten.compact.uniq.map(&:to_s) : []
61
+
62
+ wantedMethods = includeMethods - excludeMethods
63
+
64
+ $DEBUG_POTRUBI_BOOTSTRAP && potrubi_bootstrap_logger_ms(eye, "wantedMethods >#{wantedMethods}< knownMethods >#{knownMethods}< includeMethods >#{includeMethods}< excludeMethods >#{excludeMethods}<")
65
+
66
+ croakRegexp = Regexp.new(/(.*)_or_croak\?*/)
67
+ croakMethods = wantedMethods.map {|m| (mD = m.match(croakRegexp)) ? mD[1] : nil }.compact
68
+
69
+ croakUndefinedMethods = croakMethods.reject {|m| knownMethods.include?(m) } # method already defined?
70
+
71
+ $DEBUG_POTRUBI_BOOTSTRAP && potrubi_bootstrap_logger_ms(eye, "croakUndefinedMethods >#{croakUndefinedMethods.class}< >#{croakUndefinedMethods}< croakMethods >#{croakMethods}<")
72
+
73
+ croakUndefinedMethodsHash = Hash[*croakUndefinedMethods.map {|m| [m, nil]}.flatten]
74
+
75
+ recipe_rescue_croak(targetModule, croakUndefinedMethodsHash)
76
+
77
+ $DEBUG_POTRUBI_BOOTSTRAP && potrubi_bootstrap_logger_mx(eye, "targetModule >#{targetModule.class}< >#{targetModule}< croakUndefinedMethods >#{croakUndefinedMethodsHash}<")
78
+
79
+ self
80
+ end
81
+ #=end
82
+
83
+
84
+
85
+ end
86
+ #=end
87
+
88
+ module Potrubi
89
+ module Mixin
90
+ module DynamicRecipes
91
+ end
92
+ end
93
+ end
94
+
95
+ Potrubi::Mixin::DynamicRecipes.extend(metaclassMethods)
96
+ Potrubi::Mixin::DynamicRecipes.__send__(:include, metaclassMethods) # Instance Methods
97
+
98
+
99
+ __END__
100
+
@@ -0,0 +1,315 @@
1
+
2
+ # potrubi mixin dynamic
3
+
4
+ # dynamic method, etc generation
5
+
6
+ require_relative '../bootstrap'
7
+
8
+ metaclassMethods = Module.new do
9
+
10
+ include Potrubi::Bootstrap
11
+
12
+ #=begin
13
+ def dynamic_apply_edits(editSpecInput, *textValues, &block)
14
+ eye = :dyn_apy_edts
15
+ eyeTale = '"TEXT EDITS'
16
+
17
+ #editSpec.is_a?(Hash) || editSpec.is_a?(Enumerator) || (raise ArgumentError,"editSpec >#{editSpec.class}< >#{editSpec}< not hash")
18
+ editSpec = case editSpecInput
19
+ when Hash then editSpecInput
20
+ when Array then dynamic_merge_edits(editSpecInput)
21
+ when NilClass then nil
22
+ else
23
+ potrubi_bootstrap_surpise_exception(editSpecInput, eye, "editSpecInput not has, array or nil")
24
+ ###nil # will error
25
+ end
26
+
27
+ editSpec && potrubi_bootstrap_mustbe_hash_or_croak(editSpec, "editSpec not hash")
28
+
29
+ #potrubi_bootstrap_logger_me(eye, eyeTale, "editSpec", editSpec, "textValues >\n#{textValues}")
30
+
31
+ textValue = textValues.flatten.compact.join("\n")
32
+
33
+ textFinal = case editSpec
34
+ when NilClass then textValue
35
+ else
36
+
37
+ newtextValue = nil
38
+
39
+ recurseMax = 16
40
+ recurseCnt = 0
41
+ until (textValue == newtextValue)
42
+
43
+ ((recurseCnt +=1) <= recurseMax) || potrubi_bootstrap_surprise_exception(recurseCnt, eye, "recurseMax >#{recurseMax}< exceeded")
44
+
45
+ textValue = newtextValue || textValue
46
+ newtextValue = editSpec.inject(textValue) { |txt, (key, val)| txt.gsub(/#{key}/,"#{val}") }
47
+ ###puts("APY EDTS recurseCnt >#{recurseCnt}< newtestValue >#{newtextValue}<")
48
+ end
49
+
50
+ newtextValue
51
+
52
+ end
53
+
54
+ # support for uniquenesses needed?
55
+
56
+ #while (textFinal =~ /METHOD_UNIQUENESS/)
57
+ # textFinal = textFinal.sub(/METHOD_UNIQUENESS/, rand(1000000000000).to_s) # Each UNQIUENESS is unique!
58
+ #end
59
+
60
+ #potrubi_bootstrap_logger_mx(eye, eyeTale, "textFinal >#{textFinal.class}< >\n#{textFinal}\n<")
61
+
62
+ textFinal
63
+
64
+ end
65
+ #=end
66
+
67
+ #=begin
68
+ def dynamic_merge_edits(*edits)
69
+ r = edits.flatten.compact.inject({}) {|s, h| s.merge(potrubi_bootstrap_mustbe_hash_or_croak(h))}
70
+ r.empty? ? nil : r
71
+ end
72
+ #=end
73
+
74
+ #=begin
75
+ def dynamic_define_methods(targetModule, methodDefs, dynArgs=nil, &dynBlok)
76
+ eye = :dyn_def_mtds
77
+
78
+ $DEBUG_POTRUBI_BOOTSTRAP && potrubi_bootstrap_logger_me(eye, "targetModule >#{targetModule.class}< >#{targetModule}< specs >#{methodDefs.class}< >#{methodDefs}< dynArgs >#{dynArgs.class}< >#{dynArgs}< dynBlok >#{dynBlok}<")
79
+
80
+ potrubi_bootstrap_mustbe_module_or_croak(targetModule, eye, "targetModule not module")
81
+
82
+ potrubi_bootstrap_mustbe_hash_or_croak(methodDefs, eye, "methodDefs not hash")
83
+
84
+ dynArgs && potrubi_bootstrap_mustbe_hash_or_croak(dynArgs, eye, "dynArgs not hash")
85
+
86
+ editArgs = dynArgs && dynArgs[:edit]
87
+
88
+ #methodTexts = nil # will hold texts for methods, if any (could be all define_methods)
89
+
90
+ dynSpecsAll = methodDefs.map do | mtdKey, mtdVal |
91
+
92
+ $DEBUG_POTRUBI_BOOTSTRAP && potrubi_bootstrap_logger(eye, "BEG MTH mtdKey >#{mtdKey.class}< >#{mtdKey}< mtdVal >#{mtdVal.class}< >#{mtdVal.class}< editArgs >#{editArgs .class}< >#{editArgs}<")
93
+
94
+ mtdValCollection = case mtdVal
95
+ when Array then mtdVal
96
+ when Hash, String, Symbol, Proc then [mtdVal]
97
+ when NilClass then [mtdKey]
98
+ else
99
+ potrubi_bootstrap_surprise_exception(mtdVal, eye, "mtdVal is what?")
100
+ end
101
+
102
+ dynResultsBlok = Kernel.block_given? ? mtdValCollection.map {|v| dynBlok.call(mtdKey, v) } : mtdValCollection
103
+
104
+ $DEBUG_POTRUBI_BOOTSTRAP && potrubi_bootstrap_logger(eye, "CASE GEN mtdKey >#{mtdKey.class}< >#{mtdKey}< mtdVal >#{mtdVal.class}< >#{mtdVal}< dynResultsBlok >#{dynResultsBlok.class}< >#{dynResultsBlok}<")
105
+
106
+ editMtd = nil # no default edits
107
+
108
+ dynResultsNorm = [dynResultsBlok].flatten(1).map do | dynResult |
109
+ case dynResult
110
+ when NilClass then nil
111
+ when Array then
112
+ $DEBUG_POTRUBI_BOOTSTRAP && potrubi_bootstrap_logger_ms(eye, "CASE ARRAY mtdKey >#{mtdKey.class}< >#{mtdKey}< dynResult >#{dynResult.class}< >#{dynResult}<")
113
+ dynResult # expected to have got is all right
114
+ when String, Symbol then
115
+ $DEBUG_POTRUBI_BOOTSTRAP && potrubi_bootstrap_logger_ms(eye, "CASE STRING, SYMBOL mtdKey >#{mtdKey.class}< >#{mtdKey}< dynResult >#{dynResult.class}< >#{dynResult}<")
116
+ #{:edit => [editMtd, editArgs], :spec => dynResult}
117
+ {spec: dynResult}
118
+ when Proc then
119
+ $DEBUG_POTRUBI_BOOTSTRAP && potrubi_bootstrap_logger_ms(eye, "CASE PROC mtdKey >#{mtdKey.class}< >#{mtdKey}< dynResult >#{dynResult.class}< >#{dynResult}<")
120
+ {name: mtdKey, spec: dynResult}
121
+ when Hash then
122
+ $DEBUG_POTRUBI_BOOTSTRAP && potrubi_bootstrap_logger_ms(eye, "CASE HASH mtdVal >#{mtdKey.class}< >#{mtdKey}< dynResult >#{dynResult.class}< >#{dynResult}<")
123
+ dynResult # expected to have gotten it right
124
+ else
125
+ potrubi_bootstrap_surprise_exception(dynResult, eye, "dynResult is what?")
126
+ end
127
+
128
+ end.flatten.compact
129
+
130
+
131
+ dynSpecs = [*dynResultsNorm].map do | dynResult |
132
+
133
+ potrubi_bootstrap_mustbe_hash_or_croak(dynResult, eye, "dynResult not hash")
134
+
135
+ editAll = case
136
+ when dynResult.has_key?(:edit) then # edit key set?
137
+ editLocal = dynResult[:edit]
138
+ # if edit key is nil => NO EDITS AT ALL
139
+ editLocal ? [editMtd, editArgs, editLocal] : nil
140
+ else
141
+ # wants defaults; there was no point returning hash
142
+ [editMtd, editArgs]
143
+ end
144
+
145
+ editAll ? dynResult.merge({:edit => editAll}) : dynResult
146
+
147
+ end
148
+
149
+ $DEBUG_POTRUBI_BOOTSTRAP && potrubi_bootstrap_logger_ms(eye, "FIN MTH mtdKey >#{mtdKey.class}< >#{mtdKey}< dynSpecs >#{dynSpecs.class}< >#{dynSpecs}<")
150
+
151
+
152
+ #dynamic_define_methods_apply(targetModule, dynSpecs)
153
+ dynSpecs
154
+ end
155
+
156
+ dynamic_define_methods_apply(targetModule, dynSpecsAll)
157
+
158
+
159
+ $DEBUG_POTRUBI_BOOTSTRAP && potrubi_bootstrap_logger_mx(eye, "targetModule >#{targetModule.class}< >#{targetModule}< specs >#{methodDefs.class}< >#{methodDefs.class}< dynArgs >#{dynArgs.class}< >#{dynArgs}<")
160
+ self
161
+
162
+ end
163
+ #=end
164
+
165
+ #=begin
166
+ def dynamic_define_methods_apply(targetModule, *methodSpecs, &dynBlok)
167
+ eye = :ddm_apl
168
+ eyeTale = 'DDM APL'
169
+
170
+ $DEBUG_POTRUBI_BOOTSTRAP && potrubi_bootstrap_logger_me(eye, eyeTale, "targetModule >#{targetModule.class}< >#{targetModule}< specs >#{methodSpecs.class}< >#{methodSpecs.size}< >#{methodSpecs.class}< dynBlok >#{dynBlok}<")
171
+
172
+ # try to merge all the text methods together
173
+
174
+ textMethods = []
175
+
176
+ methodSpecs.flatten.compact.each_with_index do | methodSpec, methodNdx |
177
+
178
+ $DEBUG_POTRUBI_BOOTSTRAP && potrubi_bootstrap_logger_ms(eye, eyeTale, "methodNdx >#{methodNdx}< methodSpec >#{methodSpec.class}< >#{methodSpec}<")
179
+
180
+ potrubi_bootstrap_mustbe_hash_or_croak(methodSpec)
181
+
182
+ case (specType = methodSpec[:spec])
183
+ when Proc then
184
+
185
+ specName = potrubi_bootstrap_mustbe_string_or_croak((r = methodSpec[:name]) ? r.to_s : nil)
186
+ specProc = specType # potrubi_bootstrap_mustbe_proc_or_croak(mustbe_key_or_croak(methodSpec, :proc))
187
+
188
+ $DEBUG_POTRUBI_BOOTSTRAP && potrubi_bootstrap_logger(eye, eyeTale, "PROC BEG specName >#{specName.class}< >#{specName}< specProc >#{specProc.class}< >#{specProc}<")
189
+
190
+ textMethods.empty? || begin # any text methods "waiting"; must be serial defined before proc
191
+ dynamic_define_methods_apply_texts(targetModule, *textMethods)
192
+ textMethods.clear # none wating now
193
+ end
194
+
195
+ targetModule.__send__(:define_method, specName.to_sym, &specProc)
196
+
197
+ $DEBUG_POTRUBI_BOOTSTRAP && potrubi_bootstrap_logger(eye, eyeTale, "PROC FIN specName >#{specName.class}< >#{specName}< specProc >#{specProc.class}< >#{specProc}<")
198
+
199
+ when String, Symbol then textMethods << methodSpec
200
+ when Array then textMethods << methodSpec
201
+ else
202
+ potrubi_bootstrap_surprise_exception(specType, "methodSpec >#{methodSpec.class}< >#{methodSpec.class}< specType >#{specType.class}< is what?")
203
+ end
204
+
205
+ end
206
+
207
+ $DEBUG_POTRUBI_BOOTSTRAP && potrubi_bootstrap_logger(eye, eyeTale, "TXTS textMethods >#{textMethods.class}< >#{textMethods}<")
208
+
209
+ textMethods.empty? || dynamic_define_methods_apply_texts(targetModule, *textMethods)
210
+
211
+ $DEBUG_POTRUBI_BOOTSTRAP && potrubi_bootstrap_logger_mx(eye, eyeTale, "targetModule >#{targetModule.class}< >#{targetModule}< specs >#{methodSpecs.class}< >#{methodSpecs.size}<")
212
+
213
+ self
214
+
215
+ end
216
+ #=end
217
+
218
+ def dynamic_define_methods_apply_texts(targetModule, *methodSpecs, &dynBlok)
219
+ eye = :ddm_apl_txt
220
+ eyeTale = 'DDM APL TXTS'
221
+
222
+ $DEBUG_POTRUBI_BOOTSTRAP && potrubi_bootstrap_logger_me(eye, eyeTale, "targetModule >#{targetModule.class}< >#{targetModule}< specs >#{methodSpecs.class}< >#{methodSpecs}<")
223
+
224
+ #STOPAPPLYTEXTS
225
+
226
+ begin
227
+
228
+ methodTexts = methodSpecs.flatten.compact.map do | methodSpec |
229
+
230
+ $DEBUG_POTRUBI_BOOTSTRAP && potrubi_bootstrap_logger(eye, eyeTale, "BEG methodSpec >#{methodSpec.class}< >#{methodSpec}<\n\n\n")
231
+
232
+ potrubi_bootstrap_mustbe_hash_or_croak(methodSpec)
233
+
234
+ ###methodTextNom = potrubi_bootstrap_mustbe_string_or_croak([methodSpec[:spec]].flatten.compact.join)
235
+
236
+ methodEdit = methodSpec[:edit]
237
+ methodText = methodSpec[:spec]
238
+
239
+ $DEBUG_POTRUBI_BOOTSTRAP && potrubi_bootstrap_logger(eye, eyeTale, "EDIT & SPEC methodEdit >#{methodEdit}< methodText >#{methodText.class}< >#{methodText}<")
240
+
241
+ #STOPEDITANDTEXT
242
+
243
+ # Resolve any snippets
244
+
245
+ #methodSnipNom = potrubi_bootstrap_mustbe_string_or_croak(Potrubi::Mixin::TextSnippets.map_snippets_or_croak(:dynamic_methods, *methodText).flatten.compact.join)
246
+ methodSnippets = Potrubi::Mixin::TextSnippets.map_snippets_or_croak(:dynamic_methods, *methodText)
247
+
248
+ $DEBUG_POTRUBI_BOOTSTRAP && potrubi_bootstrap_logger(eye, eyeTale, "SNIP methodSnippets >#{methodSnippets.class}< >#{methodSnippets}<")
249
+
250
+ #STOPMETHODSNIPNOM
251
+
252
+ snipEdits = []
253
+
254
+ snipTexts = methodSnippets.inject([]) do | textList, snipItem |
255
+
256
+ ###puts("\nSNIP ITEM >#{snipItem.class}< >#{snipItem}<")
257
+
258
+ textList << case snipItem
259
+ when Hash
260
+ snipEdits << snipItem[:edit] # collect any edits e.g. defaults
261
+ ###potrubi_bootstrap_mustbe_string_or_croak(snipItem[:spec]) # return the text
262
+ snipItem[:spec]
263
+ when String then snipItem
264
+ else
265
+ potrubi_bootstrap_surprise_exception(methodTextNom, eye, "methodTextNom unexpected")
266
+ end
267
+
268
+ end
269
+
270
+ methodText = dynamic_apply_edits([snipEdits, methodEdit], snipTexts) # note order of edits
271
+
272
+ $DEBUG_POTRUBI_BOOTSTRAP && potrubi_bootstrap_logger(eye, eyeTale, "FIN methodEdit >#{methodEdit}< snipEdits >#{snipEdits}< methodText >#{methodText}<\n\n\n")
273
+
274
+ #STOPMETHODFIN
275
+
276
+ methodText
277
+
278
+ end.flatten.compact.join("\n")
279
+ rescue Exception => e
280
+ $DEBUG_POTRUBI_BOOTSTRAP && potrubi_bootstrap_logger(eye,"exception >#{e}<")
281
+ stopINDYNAPP3RESCUE
282
+ end
283
+
284
+ $DEBUG_POTRUBI_BOOTSTRAP && potrubi_bootstrap_logger(eye, eyeTale, "METHODS targetModule >#{targetModule.class}< >#{targetModule}< methodTexts >#{methodTexts.class}< >\n#{methodTexts}\n<")
285
+
286
+ methodTexts && targetModule.module_eval(methodTexts)
287
+
288
+ $DEBUG_POTRUBI_BOOTSTRAP && potrubi_bootstrap_logger(eye, eyeTale, "targetModule >#{targetModule.class}< >#{targetModule}< specs >#{methodSpecs.class}< >#{methodSpecs.size}<")
289
+
290
+ self
291
+
292
+ end
293
+ #=end
294
+
295
+ end
296
+ #=end
297
+
298
+ module Potrubi
299
+ module Mixin
300
+ module Dynamic
301
+ end
302
+ end
303
+ end
304
+
305
+ Potrubi::Mixin::Dynamic.extend(metaclassMethods) # Module methods
306
+ Potrubi::Mixin::Dynamic.__send__(:include, metaclassMethods) # Instance Methods
307
+
308
+ # must be after dynamic is up
309
+
310
+ requireList = %w(text-snippets)
311
+ requireList.each {|r| require_relative "#{r}"}
312
+
313
+ __END__
314
+
315
+