ree 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +3 -0
  3. data/.rubocop.yml +13 -0
  4. data/.ruby-version +1 -0
  5. data/CHANGELOG.md +5 -0
  6. data/CODE_OF_CONDUCT.md +84 -0
  7. data/Gemfile +9 -0
  8. data/Gemfile.lock +41 -0
  9. data/LICENSE.txt +21 -0
  10. data/README.md +474 -0
  11. data/Rakefile +8 -0
  12. data/bin/console +8 -0
  13. data/bin/setup +8 -0
  14. data/exe/ree +264 -0
  15. data/lib/ree/args.rb +34 -0
  16. data/lib/ree/bean_dsl.rb +24 -0
  17. data/lib/ree/cli/generate_package.rb +18 -0
  18. data/lib/ree/cli/generate_package_schema.rb +54 -0
  19. data/lib/ree/cli/generate_packages_schema.rb +17 -0
  20. data/lib/ree/cli/generate_template.rb +20 -0
  21. data/lib/ree/cli/init.rb +22 -0
  22. data/lib/ree/cli/spec_runner.rb +184 -0
  23. data/lib/ree/cli.rb +12 -0
  24. data/lib/ree/container.rb +67 -0
  25. data/lib/ree/contracts/arg_contracts/any.rb +15 -0
  26. data/lib/ree/contracts/arg_contracts/array_of.rb +52 -0
  27. data/lib/ree/contracts/arg_contracts/block.rb +15 -0
  28. data/lib/ree/contracts/arg_contracts/bool.rb +21 -0
  29. data/lib/ree/contracts/arg_contracts/eq.rb +28 -0
  30. data/lib/ree/contracts/arg_contracts/exactly.rb +28 -0
  31. data/lib/ree/contracts/arg_contracts/hash_of.rb +59 -0
  32. data/lib/ree/contracts/arg_contracts/ksplat.rb +141 -0
  33. data/lib/ree/contracts/arg_contracts/kwargs.rb +22 -0
  34. data/lib/ree/contracts/arg_contracts/nilor.rb +16 -0
  35. data/lib/ree/contracts/arg_contracts/none.rb +15 -0
  36. data/lib/ree/contracts/arg_contracts/optblock.rb +11 -0
  37. data/lib/ree/contracts/arg_contracts/or.rb +30 -0
  38. data/lib/ree/contracts/arg_contracts/range_of.rb +51 -0
  39. data/lib/ree/contracts/arg_contracts/set_of.rb +54 -0
  40. data/lib/ree/contracts/arg_contracts/splat.rb +297 -0
  41. data/lib/ree/contracts/arg_contracts/splat_of.rb +64 -0
  42. data/lib/ree/contracts/arg_contracts/squarable.rb +11 -0
  43. data/lib/ree/contracts/arg_contracts/subclass_of.rb +28 -0
  44. data/lib/ree/contracts/arg_contracts.rb +29 -0
  45. data/lib/ree/contracts/called_args_validator.rb +291 -0
  46. data/lib/ree/contracts/contract_definition.rb +142 -0
  47. data/lib/ree/contracts/contractable.rb +34 -0
  48. data/lib/ree/contracts/core.rb +17 -0
  49. data/lib/ree/contracts/engine.rb +71 -0
  50. data/lib/ree/contracts/engine_proxy.rb +13 -0
  51. data/lib/ree/contracts/errors/bad_contract_error.rb +4 -0
  52. data/lib/ree/contracts/errors/contract_error.rb +4 -0
  53. data/lib/ree/contracts/errors/error.rb +4 -0
  54. data/lib/ree/contracts/errors/return_contract_error.rb +4 -0
  55. data/lib/ree/contracts/method_decorator.rb +158 -0
  56. data/lib/ree/contracts/truncatable.rb +9 -0
  57. data/lib/ree/contracts/utils.rb +9 -0
  58. data/lib/ree/contracts/validators/array_validator.rb +51 -0
  59. data/lib/ree/contracts/validators/base_validator.rb +27 -0
  60. data/lib/ree/contracts/validators/class_validator.rb +17 -0
  61. data/lib/ree/contracts/validators/default_validator.rb +20 -0
  62. data/lib/ree/contracts/validators/hash_validator.rb +100 -0
  63. data/lib/ree/contracts/validators/proc_validator.rb +17 -0
  64. data/lib/ree/contracts/validators/range_validator.rb +17 -0
  65. data/lib/ree/contracts/validators/regexp_validator.rb +17 -0
  66. data/lib/ree/contracts/validators/valid_validator.rb +28 -0
  67. data/lib/ree/contracts/validators.rb +42 -0
  68. data/lib/ree/contracts.rb +45 -0
  69. data/lib/ree/core/link_validator.rb +42 -0
  70. data/lib/ree/core/object.rb +132 -0
  71. data/lib/ree/core/object_error.rb +9 -0
  72. data/lib/ree/core/object_link.rb +21 -0
  73. data/lib/ree/core/object_schema.rb +47 -0
  74. data/lib/ree/core/object_schema_builder.rb +110 -0
  75. data/lib/ree/core/package.rb +177 -0
  76. data/lib/ree/core/package_dep.rb +9 -0
  77. data/lib/ree/core/package_env_var.rb +12 -0
  78. data/lib/ree/core/package_loader.rb +95 -0
  79. data/lib/ree/core/package_schema.rb +27 -0
  80. data/lib/ree/core/package_schema_builder.rb +53 -0
  81. data/lib/ree/core/package_schema_loader.rb +170 -0
  82. data/lib/ree/core/packages_detector.rb +43 -0
  83. data/lib/ree/core/packages_schema.rb +19 -0
  84. data/lib/ree/core/packages_schema_builder.rb +50 -0
  85. data/lib/ree/core/packages_schema_loader.rb +95 -0
  86. data/lib/ree/core/packages_schema_locator.rb +27 -0
  87. data/lib/ree/core/packages_store.rb +32 -0
  88. data/lib/ree/core/path_helper.rb +104 -0
  89. data/lib/ree/dsl/build_package_dsl.rb +155 -0
  90. data/lib/ree/dsl/domain_error.rb +4 -0
  91. data/lib/ree/dsl/error_builder.rb +39 -0
  92. data/lib/ree/dsl/error_dsl.rb +27 -0
  93. data/lib/ree/dsl/import_dsl.rb +106 -0
  94. data/lib/ree/dsl/link_import_builder.rb +66 -0
  95. data/lib/ree/dsl/object_dsl.rb +319 -0
  96. data/lib/ree/dsl/object_hooks.rb +6 -0
  97. data/lib/ree/dsl/package_require.rb +44 -0
  98. data/lib/ree/error.rb +11 -0
  99. data/lib/ree/facades/packages_facade.rb +197 -0
  100. data/lib/ree/fn_dsl.rb +24 -0
  101. data/lib/ree/gen/init.rb +64 -0
  102. data/lib/ree/gen/package.rb +56 -0
  103. data/lib/ree/gen.rb +8 -0
  104. data/lib/ree/handlers/template_handler.rb +118 -0
  105. data/lib/ree/link_dsl.rb +175 -0
  106. data/lib/ree/object_compiler.rb +149 -0
  107. data/lib/ree/package_dsl.rb +34 -0
  108. data/lib/ree/rspec_link_dsl.rb +19 -0
  109. data/lib/ree/spec_runner/command_generator.rb +49 -0
  110. data/lib/ree/spec_runner/command_params.rb +9 -0
  111. data/lib/ree/spec_runner/runner.rb +200 -0
  112. data/lib/ree/spec_runner/spec_filename_matcher.rb +27 -0
  113. data/lib/ree/spec_runner/view.rb +30 -0
  114. data/lib/ree/spec_runner.rb +11 -0
  115. data/lib/ree/templates/init/.gitignore +1 -0
  116. data/lib/ree/templates/init/.irbrc +13 -0
  117. data/lib/ree/templates/init/.rspec +3 -0
  118. data/lib/ree/templates/init/.ruby-version +1 -0
  119. data/lib/ree/templates/init/Gemfile +7 -0
  120. data/lib/ree/templates/init/Packages.schema.json +1 -0
  121. data/lib/ree/templates/init/bin/console +5 -0
  122. data/lib/ree/templates/init/readme.md +2 -0
  123. data/lib/ree/templates/init/ree.setup.rb +21 -0
  124. data/lib/ree/templates/init/spec.init.rb +7 -0
  125. data/lib/ree/templates/package/.gitignore +0 -0
  126. data/lib/ree/templates/package/.rspec +2 -0
  127. data/lib/ree/templates/package/<%=package_subdir_name%>/<%=package_name%>/.gitkeep +0 -0
  128. data/lib/ree/templates/package/<%=package_subdir_name%>/<%=package_name%>.rb +15 -0
  129. data/lib/ree/templates/package/Package.schema.json +0 -0
  130. data/lib/ree/templates/package/bin/console +5 -0
  131. data/lib/ree/templates/package/spec/package_schema_spec.rb +14 -0
  132. data/lib/ree/templates/package/spec/spec_helper.rb +3 -0
  133. data/lib/ree/templates/template_detector.rb +35 -0
  134. data/lib/ree/templates/template_renderer.rb +55 -0
  135. data/lib/ree/utils/render_utils.rb +20 -0
  136. data/lib/ree/utils/string_utils.rb +29 -0
  137. data/lib/ree/version.rb +5 -0
  138. data/lib/ree.rb +279 -0
  139. data/sig/ree.rbs +4 -0
  140. metadata +199 -0
@@ -0,0 +1,297 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'set'
4
+
5
+ module Ree::Contracts
6
+ module ArgContracts
7
+ class Splat
8
+ include Ree::Contracts::Truncatable
9
+
10
+ def self.[](*contracts)
11
+ if contracts.empty?
12
+ raise BadContractError, 'Splat contract should accept at least one contract'
13
+ end
14
+
15
+ forbidden_class_contracts = Ree::Contracts::Validators::FORBIDDEN_CONTRACTS
16
+ forbidden = Set.new(forbidden_class_contracts.to_a - [ArgContracts::SplatOf])
17
+
18
+ contracts.each_with_index do |contract, index|
19
+ contract_name = if forbidden_class_contracts.include?(contract)
20
+ contract.to_s
21
+ elsif forbidden.include?(contract.class)
22
+ contract.class.to_s
23
+ end
24
+
25
+ if contract_name
26
+ raise BadContractError, "#{contract_name} contract is not allowed to use inside Splat contract"
27
+ end
28
+ end
29
+
30
+ splat_of_count = contracts.count { _1.is_a?(ArgContracts::SplatOf) }
31
+
32
+ if splat_of_count != 1
33
+ raise BadContractError, "Splat contract should include one SplatOf contract"
34
+ end
35
+
36
+ new(contracts)
37
+ end
38
+
39
+ def initialize(contracts)
40
+ @contracts = contracts
41
+
42
+ @first_splat_of = contracts.first.is_a?(ArgContracts::SplatOf) ? contracts.first : nil
43
+ @last_splat_of = contracts.size > 1 && contracts.last.is_a?(ArgContracts::SplatOf) ? contracts.last : nil
44
+
45
+ @middle_splat_of = if contracts.size > 2
46
+ list = contracts[1..-2]
47
+ idx = list.index { _1.is_a?(ArgContracts::SplatOf) }
48
+ list[idx] if idx
49
+ end
50
+
51
+ @middle_splat_of_index = @contracts.index { _1 == @middle_splat_of } if @middle_splat_of
52
+ @validators = contracts.map { Validators.fetch_for(_1) }
53
+ end
54
+
55
+ def valid?(value)
56
+ return false if !value.is_a?(Array)
57
+ return false if @validators.size - 1 > value.size
58
+
59
+ if @first_splat_of
60
+ return valid_with_first?(@validators, value)
61
+ end
62
+
63
+ if @last_splat_of
64
+ return valid_with_last?(@validators, value)
65
+ end
66
+
67
+ if @middle_splat_of
68
+ # before splat part
69
+ left_contract_count = @middle_splat_of_index
70
+ right_contract_count = @validators.size - @middle_splat_of_index - 1
71
+
72
+ is_valid = value[0..left_contract_count - 1].each_with_index.all? do |value, idx|
73
+ @validators[idx].call(value)
74
+ end
75
+
76
+ return false if !is_valid
77
+
78
+ # splat part
79
+ splat_values = if left_contract_count + right_contract_count == value.size
80
+ []
81
+ else
82
+ value[@middle_splat_of_index..value.size - right_contract_count - 1]
83
+ end
84
+
85
+ if !splat_values.empty?
86
+ return false if !@validators[@middle_splat_of_index].call(splat_values)
87
+ end
88
+
89
+ # after splat part
90
+ is_valid = value[value.size - right_contract_count..-1].each_with_index.all? do |value, idx|
91
+ @validators[@middle_splat_of_index + idx + 1].call(value)
92
+ end
93
+
94
+ return false if !is_valid
95
+ end
96
+
97
+ return true
98
+ end
99
+
100
+ def to_s
101
+ "Splat[#{@validators.map(&:to_s).join(", ")}]"
102
+ end
103
+
104
+ def message(value, name, lvl = 1)
105
+ unless value.is_a?(Array)
106
+ return "expected #{to_s}, got #{value.class} => #{truncate(value.inspect)}"
107
+ end
108
+
109
+ errors = []
110
+ sps = " " * lvl
111
+
112
+ if @validators.size - 1 > value.size
113
+ return "expected at least #{@validators.size - 1} #{pluralize(@validators.size, 'value', 'values')} for #{to_s}, got #{value.size} #{pluralize(value.size, 'value', 'values')} => #{truncate(value.inspect)}"
114
+ end
115
+
116
+ if @first_splat_of
117
+ rest_validators = @validators[1..-1]
118
+ rest_validator_count = rest_validators.size
119
+
120
+ rest_values = if value.size >= @validators.size
121
+ value[(value.size - rest_validator_count)..-1]
122
+ else
123
+ value
124
+ end
125
+
126
+ if rest_validator_count > 0
127
+ rest_validators.each_with_index do |validator, idx|
128
+ val = rest_values[idx]
129
+ next if validator.call(val)
130
+
131
+ msg = validator.message(val, "#{name}[#{idx + 1}]", lvl + 1)
132
+ errors << "\n\t#{sps} - #{name}[#{idx + 1}]: #{msg}"
133
+
134
+ if errors.size > 3
135
+ errors << "\n\t#{sps} - ..."
136
+ break
137
+ end
138
+ end
139
+ end
140
+
141
+ if rest_values.size != value.size
142
+ validator = @validators.first
143
+ idx = value.size - rest_validator_count - 1
144
+ val = value[0..idx]
145
+
146
+ if !validator.call(val)
147
+ msg = validator.message(val, "#{name}[0..#{idx}]", lvl + 1)
148
+ errors << "\n\t#{sps} - #{name}[0..#{idx}]: #{msg}"
149
+ end
150
+ end
151
+ elsif @last_splat_of
152
+ rest_validators = @validators[0..-2]
153
+ rest_validator_count = rest_validators.size
154
+
155
+ rest_values = if value.size >= @validators.size
156
+ value[0..-2]
157
+ else
158
+ value
159
+ end
160
+
161
+ if rest_validator_count > 0
162
+ rest_validators.each_with_index do |validator, idx|
163
+ val = rest_values[idx]
164
+ next if validator.call(val)
165
+
166
+ msg = validator.message(val, "#{name}[#{idx}]", lvl + 1)
167
+ errors << "\n\t#{sps} - #{name}[#{idx}]: #{msg}"
168
+
169
+ if errors.size > 3
170
+ errors << "\n\t#{sps} - ..."
171
+ break
172
+ end
173
+ end
174
+ end
175
+
176
+ if rest_values.size != value.size
177
+ validator = @validators.last
178
+ idx = rest_validator_count
179
+ val = value[idx..-1]
180
+
181
+ if !validator.call(val)
182
+ msg = validator.message(val, "#{name}[#{idx}..#{value.size - 1}]", lvl + 1)
183
+ errors << "\n\t#{sps} - #{name}[#{idx}..#{value.size - 1}]: #{msg}"
184
+ end
185
+ end
186
+ elsif @middle_splat_of
187
+ left_contract_count = @middle_splat_of_index
188
+ right_contract_count = @validators.size - @middle_splat_of_index - 1
189
+
190
+ value[0..left_contract_count - 1].each_with_index do |value, idx|
191
+ validator = @validators[idx]
192
+ next if validator.call(value)
193
+
194
+ msg = validator.message(value, "#{name}[#{idx}]", lvl + 1)
195
+ errors << "\n\t#{sps} - #{name}[#{idx}]: #{msg}"
196
+
197
+ if errors.size > 3
198
+ errors << "\n\t#{sps} - ..."
199
+ break
200
+ end
201
+ end
202
+
203
+ splat_values = if left_contract_count + right_contract_count == value.size
204
+ []
205
+ else
206
+ value[@middle_splat_of_index..value.size - right_contract_count - 1]
207
+ end
208
+
209
+ if !splat_values.empty?
210
+ validator = @validators[@middle_splat_of_index]
211
+
212
+ if !validator.call(splat_values)
213
+ splat_name = "#{name}[#{@middle_splat_of_index}..#{value.size - right_contract_count - 1}]"
214
+ msg = validator.message(splat_values, "#{splat_name}", lvl + 1)
215
+ errors << "\n\t#{sps} - #{splat_name}: #{msg}"
216
+ end
217
+ end
218
+
219
+ is_valid = value[value.size - right_contract_count..-1].each_with_index.all? do |value, idx|
220
+ @validators[@middle_splat_of_index + idx + 1].call(value)
221
+ end
222
+
223
+ pos = value.size - right_contract_count
224
+
225
+ value[pos..-1].each_with_index do |value, idx|
226
+ validator = @validators[@middle_splat_of_index + idx + 1]
227
+ next if validator.call(value)
228
+
229
+ msg = validator.message(value, "#{name}[#{pos + idx}]", lvl + 1)
230
+ errors << "\n\t#{sps} - #{name}[#{pos + idx}]: #{msg}"
231
+
232
+ if errors.size > 3
233
+ errors << "\n\t#{sps} - ..."
234
+ break
235
+ end
236
+ end
237
+ end
238
+
239
+ errors.join
240
+ end
241
+
242
+ private
243
+
244
+ def valid_with_first?(validators, values)
245
+ rest_validators = validators[1..-1]
246
+ rest_validator_count = rest_validators.size
247
+
248
+ rest_values = if values.size >= validators.size
249
+ values[(values.size - rest_validator_count)..-1]
250
+ else
251
+ values
252
+ end
253
+
254
+ has_error = false
255
+
256
+ if rest_validator_count > 0
257
+ has_error = rest_validators.each_with_index.any? do |validator, idx|
258
+ !validator.call(rest_values[idx])
259
+ end
260
+ end
261
+
262
+ return false if has_error
263
+ return true if rest_values.size == values.size
264
+
265
+ validators.first.call(values[0..(values.size - rest_validator_count - 1)])
266
+ end
267
+
268
+ def valid_with_last?(validators, values)
269
+ rest_validators = validators[0..-2]
270
+ rest_validator_count = rest_validators.size
271
+
272
+ rest_values = if values.size >= validators.size
273
+ values[0..-2]
274
+ else
275
+ values
276
+ end
277
+
278
+ has_error = false
279
+
280
+ if rest_validator_count > 0
281
+ has_error = rest_validators.each_with_index.any? do |validator, idx|
282
+ !validator.call(rest_values[idx])
283
+ end
284
+ end
285
+
286
+ return false if has_error
287
+ return true if rest_values.size == values.size
288
+
289
+ validators.last.call(values[rest_validator_count..-1])
290
+ end
291
+
292
+ def pluralize(num, single, plural)
293
+ num == 1 ? single : plural
294
+ end
295
+ end
296
+ end
297
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ree::Contracts
4
+ module ArgContracts
5
+ class SplatOf
6
+ include Ree::Contracts::Truncatable
7
+
8
+ attr_reader :validator
9
+
10
+ class << self
11
+ def [](contract)
12
+ new(contract)
13
+ end
14
+ end
15
+
16
+ def initialize(contract)
17
+ forbidden_class_contracts = Ree::Contracts::Validators::FORBIDDEN_CONTRACTS
18
+
19
+ contract_name = if forbidden_class_contracts.include?(contract)
20
+ contract.to_s
21
+ elsif forbidden_class_contracts.include?(contract.class)
22
+ contract.class.to_s
23
+ end
24
+
25
+ if contract_name
26
+ raise BadContractError, "#{contract_name} contract is not allowed to use inside SplatOf contract"
27
+ end
28
+
29
+ @validator = Validators.fetch_for(contract)
30
+ end
31
+
32
+ def valid?(value)
33
+ value.is_a?(Array) && value.all?(&validator.method(:call))
34
+ end
35
+
36
+ def to_s
37
+ "SplatOf[#{validator.to_s}]"
38
+ end
39
+
40
+ def message(value, name, lvl = 1)
41
+ unless value.is_a?(Array)
42
+ return "expected #{to_s}, got #{value.class} => #{truncate(value.inspect)}"
43
+ end
44
+
45
+ errors = []
46
+ sps = " " * lvl
47
+
48
+ value.each_with_index do |val, idx|
49
+ next if validator.call(val)
50
+
51
+ msg = validator.message(val, "#{name}[#{idx}]", lvl + 1)
52
+ errors << "\n\t#{sps} - #{name}[#{idx}]: #{msg}"
53
+
54
+ if errors.size > 3
55
+ errors << "\n\t#{sps} - ..."
56
+ break
57
+ end
58
+ end
59
+
60
+ errors.join
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ree::Contracts
4
+ module ArgContracts
5
+ module Squarable
6
+ def [](*args, **kwargs)
7
+ new(*args, **kwargs)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ree::Contracts
4
+ module ArgContracts
5
+ class SubclassOf
6
+ extend Ree::Contracts::ArgContracts::Squarable
7
+ include Ree::Contracts::Truncatable
8
+
9
+ attr_reader :klass
10
+
11
+ def initialize(klass)
12
+ @klass = klass
13
+ end
14
+
15
+ def valid?(value)
16
+ value.is_a?(Class) && value < klass
17
+ end
18
+
19
+ def to_s
20
+ "SubclassOf[#{klass.inspect}]"
21
+ end
22
+
23
+ def message(value, name, lvl = 1)
24
+ "expected #{truncate(self.to_s, 30)}, got #{truncate(value.inspect)}"
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ree::Contracts
4
+ module ArgContracts
5
+ autoload :Any, 'ree/contracts/arg_contracts/any'
6
+ autoload :ArrayOf, 'ree/contracts/arg_contracts/array_of'
7
+ autoload :Block, 'ree/contracts/arg_contracts/block'
8
+ autoload :Bool, 'ree/contracts/arg_contracts/bool'
9
+ autoload :Eq, 'ree/contracts/arg_contracts/eq'
10
+ autoload :Exactly, 'ree/contracts/arg_contracts/exactly'
11
+ autoload :HashOf, 'ree/contracts/arg_contracts/hash_of'
12
+ autoload :Ksplat, 'ree/contracts/arg_contracts/ksplat'
13
+ autoload :Kwargs, 'ree/contracts/arg_contracts/kwargs'
14
+ autoload :Nilor, 'ree/contracts/arg_contracts/nilor'
15
+ autoload :None, 'ree/contracts/arg_contracts/none'
16
+ autoload :Optblock, 'ree/contracts/arg_contracts/optblock'
17
+ autoload :Or, 'ree/contracts/arg_contracts/or'
18
+ autoload :RangeOf, 'ree/contracts/arg_contracts/range_of'
19
+ autoload :SetOf, 'ree/contracts/arg_contracts/set_of'
20
+ autoload :Splat, 'ree/contracts/arg_contracts/splat'
21
+ autoload :SplatOf, 'ree/contracts/arg_contracts/splat_of'
22
+ autoload :Squarable, 'ree/contracts/arg_contracts/squarable'
23
+ autoload :SubclassOf, 'ree/contracts/arg_contracts/subclass_of'
24
+
25
+ def self.opt_or_block?(contract)
26
+ contract == Block || contract == Optblock
27
+ end
28
+ end
29
+ end