potrubi 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +9 -0
- data/lib/potrubi.rb +9 -0
- data/lib/potrubi/bootstrap.rb +27 -0
- data/lib/potrubi/core.rb +33 -0
- data/lib/potrubi/klass/syntax/braket.rb +197 -0
- data/lib/potrubi/mixin/bootstrap_common.rb +125 -0
- data/lib/potrubi/mixin/configuration.rb +109 -0
- data/lib/potrubi/mixin/contract-recipes.rb +226 -0
- data/lib/potrubi/mixin/contract.rb +105 -0
- data/lib/potrubi/mixin/dynamic-recipes.rb +100 -0
- data/lib/potrubi/mixin/dynamic.rb +315 -0
- data/lib/potrubi/mixin/exception.rb +98 -0
- data/lib/potrubi/mixin/filesys.rb +89 -0
- data/lib/potrubi/mixin/initialize.rb +23 -0
- data/lib/potrubi/mixin/konstant.rb +368 -0
- data/lib/potrubi/mixin/logger.rb +178 -0
- data/lib/potrubi/mixin/pathandnames.rb +226 -0
- data/lib/potrubi/mixin/persistence.rb +192 -0
- data/lib/potrubi/mixin/script.rb +59 -0
- data/lib/potrubi/mixin/text-snippets.rb +182 -0
- data/lib/potrubi/mixin/text-snippets/methods-text-snippets.rb +254 -0
- data/lib/potrubi/mixin/util.rb +53 -0
- data/lib/potrubi/version.rb +1 -1
- metadata +27 -5
@@ -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
|
+
|