potrubi 0.0.1 → 0.0.2
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.
- 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
|
+
|