super-smart-tool 0.0.1

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 (63) hide show
  1. checksums.yaml +7 -0
  2. data/dry-types-1.9.1/CHANGELOG.md +1145 -0
  3. data/dry-types-1.9.1/LICENSE +20 -0
  4. data/dry-types-1.9.1/README.md +17 -0
  5. data/dry-types-1.9.1/dry-types.gemspec +45 -0
  6. data/dry-types-1.9.1/lib/dry/types/any.rb +41 -0
  7. data/dry-types-1.9.1/lib/dry/types/array/constructor.rb +24 -0
  8. data/dry-types-1.9.1/lib/dry/types/array/member.rb +118 -0
  9. data/dry-types-1.9.1/lib/dry/types/array.rb +32 -0
  10. data/dry-types-1.9.1/lib/dry/types/builder.rb +221 -0
  11. data/dry-types-1.9.1/lib/dry/types/builder_methods.rb +138 -0
  12. data/dry-types-1.9.1/lib/dry/types/coercions/json.rb +57 -0
  13. data/dry-types-1.9.1/lib/dry/types/coercions/params.rb +168 -0
  14. data/dry-types-1.9.1/lib/dry/types/coercions.rb +105 -0
  15. data/dry-types-1.9.1/lib/dry/types/compat.rb +1 -0
  16. data/dry-types-1.9.1/lib/dry/types/compiler.rb +138 -0
  17. data/dry-types-1.9.1/lib/dry/types/composition.rb +138 -0
  18. data/dry-types-1.9.1/lib/dry/types/constrained/coercible.rb +59 -0
  19. data/dry-types-1.9.1/lib/dry/types/constrained.rb +146 -0
  20. data/dry-types-1.9.1/lib/dry/types/constraints.rb +30 -0
  21. data/dry-types-1.9.1/lib/dry/types/constructor/function.rb +203 -0
  22. data/dry-types-1.9.1/lib/dry/types/constructor/wrapper.rb +88 -0
  23. data/dry-types-1.9.1/lib/dry/types/constructor.rb +195 -0
  24. data/dry-types-1.9.1/lib/dry/types/container.rb +12 -0
  25. data/dry-types-1.9.1/lib/dry/types/core.rb +106 -0
  26. data/dry-types-1.9.1/lib/dry/types/decorator.rb +94 -0
  27. data/dry-types-1.9.1/lib/dry/types/default.rb +122 -0
  28. data/dry-types-1.9.1/lib/dry/types/enum.rb +121 -0
  29. data/dry-types-1.9.1/lib/dry/types/errors.rb +138 -0
  30. data/dry-types-1.9.1/lib/dry/types/extensions/maybe.rb +128 -0
  31. data/dry-types-1.9.1/lib/dry/types/extensions/monads.rb +34 -0
  32. data/dry-types-1.9.1/lib/dry/types/extensions.rb +9 -0
  33. data/dry-types-1.9.1/lib/dry/types/fn_container.rb +37 -0
  34. data/dry-types-1.9.1/lib/dry/types/hash/constructor.rb +25 -0
  35. data/dry-types-1.9.1/lib/dry/types/hash.rb +134 -0
  36. data/dry-types-1.9.1/lib/dry/types/implication.rb +64 -0
  37. data/dry-types-1.9.1/lib/dry/types/inflector.rb +9 -0
  38. data/dry-types-1.9.1/lib/dry/types/intersection.rb +102 -0
  39. data/dry-types-1.9.1/lib/dry/types/json.rb +35 -0
  40. data/dry-types-1.9.1/lib/dry/types/lax.rb +66 -0
  41. data/dry-types-1.9.1/lib/dry/types/map.rb +134 -0
  42. data/dry-types-1.9.1/lib/dry/types/meta.rb +53 -0
  43. data/dry-types-1.9.1/lib/dry/types/module.rb +127 -0
  44. data/dry-types-1.9.1/lib/dry/types/nominal.rb +201 -0
  45. data/dry-types-1.9.1/lib/dry/types/options.rb +34 -0
  46. data/dry-types-1.9.1/lib/dry/types/params.rb +38 -0
  47. data/dry-types-1.9.1/lib/dry/types/predicate_inferrer.rb +235 -0
  48. data/dry-types-1.9.1/lib/dry/types/predicate_registry.rb +32 -0
  49. data/dry-types-1.9.1/lib/dry/types/primitive_inferrer.rb +75 -0
  50. data/dry-types-1.9.1/lib/dry/types/printable.rb +14 -0
  51. data/dry-types-1.9.1/lib/dry/types/printer/composition.rb +44 -0
  52. data/dry-types-1.9.1/lib/dry/types/printer.rb +313 -0
  53. data/dry-types-1.9.1/lib/dry/types/result.rb +72 -0
  54. data/dry-types-1.9.1/lib/dry/types/schema/key.rb +138 -0
  55. data/dry-types-1.9.1/lib/dry/types/schema.rb +408 -0
  56. data/dry-types-1.9.1/lib/dry/types/spec/types.rb +164 -0
  57. data/dry-types-1.9.1/lib/dry/types/sum.rb +105 -0
  58. data/dry-types-1.9.1/lib/dry/types/type.rb +53 -0
  59. data/dry-types-1.9.1/lib/dry/types/version.rb +7 -0
  60. data/dry-types-1.9.1/lib/dry/types.rb +259 -0
  61. data/dry-types-1.9.1/lib/dry-types.rb +3 -0
  62. data/super-smart-tool.gemspec +11 -0
  63. metadata +101 -0
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dry
4
+ module Types
5
+ # PrimitiveInferrer returns the list of classes matching a type.
6
+ #
7
+ # @api public
8
+ class PrimitiveInferrer
9
+ extend Core::Cache
10
+
11
+ # Compiler reduces type AST into a list of primitives
12
+ #
13
+ # @api private
14
+ class Compiler
15
+ # @api private
16
+ def visit(node)
17
+ meth, rest = node
18
+ public_send(:"visit_#{meth}", rest)
19
+ end
20
+
21
+ # @api private
22
+ def visit_nominal(node) = node[0]
23
+
24
+ # @api private
25
+ def visit_hash(_) = ::Hash
26
+ alias_method :visit_schema, :visit_hash
27
+
28
+ # @api private
29
+ def visit_array(_) = ::Array
30
+
31
+ # @api private
32
+ def visit_lax(node) = visit(node)
33
+
34
+ # @api private
35
+ def visit_constructor(node) = visit(node[0])
36
+
37
+ # @api private
38
+ def visit_enum(node) = visit(node[0])
39
+
40
+ # @api private
41
+ def visit_sum(node)
42
+ left, right = node
43
+
44
+ [visit(left), visit(right)].flatten(1)
45
+ end
46
+
47
+ # @api private
48
+ def visit_constrained(node) = visit(node[0])
49
+
50
+ # @api private
51
+ def visit_any(_) = ::Object
52
+ end
53
+
54
+ # @return [Compiler]
55
+ # @api private
56
+ attr_reader :compiler
57
+
58
+ # @api private
59
+ def initialize
60
+ @compiler = Compiler.new
61
+ end
62
+
63
+ # Infer primitives from the provided type
64
+ #
65
+ # @return [Array[Class]]
66
+ #
67
+ # @api private
68
+ def [](type)
69
+ self.class.fetch_or_store(type) do
70
+ Array(compiler.visit(type.to_ast)).freeze
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dry
4
+ module Types
5
+ # @api private
6
+ module Printable
7
+ # @return [String]
8
+ #
9
+ # @api private
10
+ def to_s = PRINTER.(self)
11
+ alias_method :inspect, :to_s
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dry
4
+ module Types
5
+ # @api private
6
+ class Printer
7
+ # @api private
8
+ class Composition
9
+ def initialize(printer, composition_class)
10
+ @printer = printer
11
+ @composition_class = composition_class
12
+ freeze
13
+ end
14
+
15
+ def visit(composition)
16
+ visit_constructors(composition) do |constructors|
17
+ @printer.visit_options(composition.options, composition.meta) do |opts|
18
+ yield "#{@composition_class.composition_name}<#{constructors}#{opts}>"
19
+ end
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ def visit_constructors(composition)
26
+ visit_constructor(composition.left) do |left|
27
+ visit_constructor(composition.right) do |right|
28
+ yield "#{left} #{@composition_class.operator} #{right}"
29
+ end
30
+ end
31
+ end
32
+
33
+ def visit_constructor(type, &)
34
+ case type
35
+ when @composition_class
36
+ visit_constructors(type, &)
37
+ else
38
+ @printer.visit(type, &)
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,313 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/types/printer/composition"
4
+
5
+ module Dry
6
+ # rubocop:disable Metrics/AbcSize
7
+ # rubocop:disable Metrics/PerceivedComplexity
8
+ module Types
9
+ # @api private
10
+ class Printer
11
+ MAPPING = {
12
+ Nominal => :visit_nominal,
13
+ Constructor => :visit_constructor,
14
+ [
15
+ Constrained,
16
+ Constrained::Coercible
17
+ ] => :visit_constrained,
18
+ Types::Hash => :visit_hash,
19
+ Schema => :visit_schema,
20
+ Schema::Key => :visit_key,
21
+ Map => :visit_map,
22
+ Array => :visit_array,
23
+ Array::Member => :visit_array_member,
24
+ Lax => :visit_lax,
25
+ Enum => :visit_enum,
26
+ [Default, Default::Callable] => :visit_default,
27
+ [
28
+ Sum,
29
+ Sum::Constrained,
30
+ Intersection,
31
+ Intersection::Constrained,
32
+ Implication,
33
+ Implication::Constrained
34
+ ] => :visit_composition,
35
+ Any.class => :visit_any
36
+ }.flat_map { |k, v| Array(k).map { |kk| [kk, v] } }.to_h
37
+
38
+ def initialize
39
+ @composition_printers = {}
40
+ freeze
41
+ end
42
+
43
+ def call(type)
44
+ output = "".dup
45
+ visit(type) { |str| output << str }
46
+ "#<Dry::Types[#{output}]>"
47
+ end
48
+
49
+ def visit(type, &)
50
+ print_with = MAPPING.fetch(type.class) do
51
+ if type.class < Constructor
52
+ :visit_constructor
53
+ elsif type.is_a?(Type)
54
+ return yield type.inspect
55
+ else
56
+ raise ArgumentError, "Do not know how to print #{type.class}"
57
+ end
58
+ end
59
+ send(print_with, type, &)
60
+ end
61
+
62
+ def visit_any(_) = yield "Any"
63
+
64
+ def visit_array(type)
65
+ visit_options(EMPTY_HASH, type.meta) do |opts|
66
+ yield "Array#{opts}"
67
+ end
68
+ end
69
+
70
+ def visit_array_member(array)
71
+ visit(array.member) do |type|
72
+ visit_options(EMPTY_HASH, array.meta) do |opts|
73
+ yield "Array<#{type}#{opts}>"
74
+ end
75
+ end
76
+ end
77
+
78
+ def visit_constructor(constructor)
79
+ visit(constructor.type) do |type|
80
+ visit_callable(constructor.fn.fn) do |fn|
81
+ options = constructor.options.dup
82
+ options.delete(:fn)
83
+
84
+ visit_options(options) do |opts|
85
+ yield "Constructor<#{type} fn=#{fn}#{opts}>"
86
+ end
87
+ end
88
+ end
89
+ end
90
+
91
+ def visit_constrained(constrained)
92
+ visit(constrained.type) do |type|
93
+ options = constrained.options.dup
94
+ rule = options.delete(:rule)
95
+
96
+ visit_options(options) do |_opts|
97
+ yield "Constrained<#{type} rule=[#{rule}]>"
98
+ end
99
+ end
100
+ end
101
+
102
+ def visit_composition(composition, &)
103
+ klass = composition.class
104
+ @composition_printers[klass] = Composition.new(self, klass)
105
+ @composition_printers[klass].visit(composition, &)
106
+ end
107
+
108
+ def visit_sum_constructors(sum)
109
+ visit_sum_constructor(sum.left) do |left|
110
+ visit_sum_constructor(sum.right) do |right|
111
+ yield "#{left} #{sum.class.operator} #{right}"
112
+ end
113
+ end
114
+ end
115
+
116
+ def visit_sum_constructor(type, &)
117
+ if type.is_a?(Dry::Types::Sum)
118
+ visit_sum_constructors(type, &)
119
+ else
120
+ visit(type, &)
121
+ end
122
+ end
123
+
124
+ def visit_enum(enum)
125
+ visit(enum.type) do |type|
126
+ options = enum.options.dup
127
+ mapping = options.delete(:mapping)
128
+
129
+ visit_options(options) do |opts|
130
+ if mapping == enum.inverted_mapping
131
+ yield "Enum(#{enum.joined_values})<#{type}#{opts}>"
132
+ else
133
+ mapping_str = mapping.map { |key, value|
134
+ "#{key.inspect}=>#{value.inspect}"
135
+ }.join(", ")
136
+ yield "Enum<#{type} mapping={#{mapping_str}}#{opts}>"
137
+ end
138
+ end
139
+ end
140
+ end
141
+
142
+ def visit_default(default)
143
+ visit(default.type) do |type|
144
+ visit_options(default.options) do |opts|
145
+ if default.is_a?(Default::Callable)
146
+ visit_callable(default.value) do |fn|
147
+ yield "Default<#{type} value_fn=#{fn}#{opts}>"
148
+ end
149
+ else
150
+ yield "Default<#{type} value=#{default.value.inspect}#{opts}>"
151
+ end
152
+ end
153
+ end
154
+ end
155
+
156
+ def visit_nominal(type)
157
+ visit_options(type.options, type.meta) do |opts|
158
+ yield "Nominal<#{type.primitive}#{opts}>"
159
+ end
160
+ end
161
+
162
+ def visit_lax(lax)
163
+ visit(lax.type) do |type|
164
+ yield "Lax<#{type}>"
165
+ end
166
+ end
167
+
168
+ def visit_callable(callable)
169
+ fn = callable.is_a?(String) ? FnContainer[callable] : callable
170
+
171
+ case fn
172
+ when ::Method
173
+ yield "#{fn.receiver}.#{fn.name}"
174
+ when ::Proc
175
+ path, line = fn.source_location
176
+
177
+ if line&.zero?
178
+ yield ".#{path}"
179
+ elsif path
180
+ yield "#{path.sub("#{Dir.pwd}/", EMPTY_STRING)}:#{line}"
181
+ else
182
+ match = fn.to_s.match(/\A#<Proc:0x\h+\(&:(?<name>\w+)\)(:? \(lambda\))?>\z/)
183
+
184
+ if match
185
+ yield ".#{match[:name]}"
186
+ elsif fn.lambda?
187
+ yield "(lambda)"
188
+ else
189
+ yield "(proc)"
190
+ end
191
+ end
192
+ else
193
+ call = fn.method(:call)
194
+
195
+ if call.owner == fn.class
196
+ yield "#{fn.class}#call"
197
+ else
198
+ yield "#{fn}.call"
199
+ end
200
+ end
201
+ end
202
+
203
+ def visit_schema(schema)
204
+ options = schema.options.dup
205
+ size = schema.count
206
+ key_fn_str = ""
207
+ type_fn_str = ""
208
+ strict_str = ""
209
+
210
+ strict_str = "strict " if options.delete(:strict)
211
+
212
+ if (key_fn = options.delete(:key_transform_fn))
213
+ visit_callable(key_fn) do |fn|
214
+ key_fn_str = "key_fn=#{fn} "
215
+ end
216
+ end
217
+
218
+ if (type_fn = options.delete(:type_transform_fn))
219
+ visit_callable(type_fn) do |fn|
220
+ type_fn_str = "type_fn=#{fn} "
221
+ end
222
+ end
223
+
224
+ keys = options.delete(:keys)
225
+
226
+ visit_options(options, schema.meta) do |opts|
227
+ opts = "#{opts[1..]} " unless opts.empty?
228
+ schema_parameters = "#{key_fn_str}#{type_fn_str}#{strict_str}#{opts}"
229
+
230
+ header = "Schema<#{schema_parameters}keys={"
231
+
232
+ if size.zero?
233
+ yield "#{header}}>"
234
+ else
235
+ yield header.dup << keys.map { |key|
236
+ visit(key) { |type| type }
237
+ }.join(" ") << "}>"
238
+ end
239
+ end
240
+ end
241
+
242
+ def visit_map(map)
243
+ visit(map.key_type) do |key|
244
+ visit(map.value_type) do |value|
245
+ options = map.options.dup
246
+ options.delete(:key_type)
247
+ options.delete(:value_type)
248
+
249
+ visit_options(options) do |_opts|
250
+ yield "Map<#{key} => #{value}>"
251
+ end
252
+ end
253
+ end
254
+ end
255
+
256
+ def visit_key(key)
257
+ visit(key.type) do |type|
258
+ if key.required?
259
+ yield "#{key.name}: #{type}"
260
+ else
261
+ yield "#{key.name}?: #{type}"
262
+ end
263
+ end
264
+ end
265
+
266
+ def visit_hash(hash)
267
+ options = hash.options.dup
268
+ type_fn_str = ""
269
+
270
+ if (type_fn = options.delete(:type_transform_fn))
271
+ visit_callable(type_fn) do |fn|
272
+ type_fn_str = "type_fn=#{fn}"
273
+ end
274
+ end
275
+
276
+ visit_options(options, hash.meta) do |opts|
277
+ if opts.empty? && type_fn_str.empty?
278
+ yield "Hash"
279
+ else
280
+ yield "Hash<#{type_fn_str}#{opts}>"
281
+ end
282
+ end
283
+ end
284
+
285
+ def visit_options(options, meta = EMPTY_HASH) # rubocop:disable Metrics/PerceivedComplexity
286
+ if options.empty? && meta.empty?
287
+ yield ""
288
+ else
289
+ opts = options.empty? ? "" : " options=#{options.inspect}"
290
+
291
+ if meta.empty?
292
+ yield opts
293
+ else
294
+ values = meta.map do |key, value|
295
+ case key
296
+ when Symbol
297
+ "#{key}: #{value.inspect}"
298
+ else
299
+ "#{key.inspect}=>#{value.inspect}"
300
+ end
301
+ end
302
+
303
+ yield "#{opts} meta={#{values.join(", ")}}"
304
+ end
305
+ end
306
+ end
307
+ end
308
+
309
+ PRINTER = Printer.new
310
+ end
311
+ # rubocop:enable Metrics/AbcSize
312
+ # rubocop:enable Metrics/PerceivedComplexity
313
+ end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dry
4
+ module Types
5
+ # Result class used by {Type#try}
6
+ #
7
+ # @api public
8
+ class Result
9
+ include ::Dry::Equalizer(:input, immutable: true)
10
+
11
+ # @return [Object]
12
+ attr_reader :input
13
+
14
+ # @param [Object] input
15
+ #
16
+ # @api private
17
+ def initialize(input)
18
+ @input = input
19
+ end
20
+
21
+ # Success result
22
+ #
23
+ # @api public
24
+ class Success < Result
25
+ # @return [true]
26
+ #
27
+ # @api public
28
+ def success? = true
29
+
30
+ # @return [false]
31
+ #
32
+ # @api public
33
+ def failure? = false
34
+ end
35
+
36
+ # Failure result
37
+ #
38
+ # @api public
39
+ class Failure < Result
40
+ include ::Dry::Equalizer(:input, :error, immutable: true)
41
+
42
+ # @return [#to_s]
43
+ attr_reader :error
44
+
45
+ # @param [Object] input
46
+ #
47
+ # @param [#to_s] error
48
+ #
49
+ # @api private
50
+ def initialize(input, error)
51
+ super(input)
52
+ @error = error
53
+ end
54
+
55
+ # @return [String]
56
+ #
57
+ # @api private
58
+ def to_s = error.to_s
59
+
60
+ # @return [false]
61
+ #
62
+ # @api public
63
+ def success? = false
64
+
65
+ # @return [true]
66
+ #
67
+ # @api public
68
+ def failure? = true
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,138 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dry
4
+ module Types
5
+ # Schema is a hash with explicit member types defined
6
+ #
7
+ # @api public
8
+ class Schema < Hash
9
+ # Proxy type for schema keys. Contains only key name and
10
+ # whether it's required or not. All other calls deletaged
11
+ # to the wrapped type.
12
+ #
13
+ # @see Dry::Types::Schema
14
+ class Key
15
+ extend ::Dry::Core::Deprecations[:"dry-types"]
16
+ include Type
17
+ include Dry::Equalizer(:name, :type, :options, inspect: false, immutable: true)
18
+ include Decorator
19
+ include Builder
20
+ include Printable
21
+
22
+ # @return [Symbol]
23
+ attr_reader :name
24
+
25
+ # @api private
26
+ def initialize(type, name, required: Undefined, **options)
27
+ required = Undefined.default(required) do
28
+ type.meta.fetch(:required) { !type.meta.fetch(:omittable, false) }
29
+ end
30
+
31
+ unless name.is_a?(::Symbol)
32
+ raise ::ArgumentError,
33
+ "Schemas can only contain symbol keys, #{name.inspect} given"
34
+ end
35
+
36
+ super
37
+ @name = name
38
+ end
39
+
40
+ # @api private
41
+ def call_safe(input, &) = type.call_safe(input, &)
42
+
43
+ # @api private
44
+ def call_unsafe(input) = type.call_unsafe(input)
45
+
46
+ # @see Dry::Types::Nominal#try
47
+ #
48
+ # @api public
49
+ def try(input, &) = type.try(input, &)
50
+
51
+ # Whether the key is required in schema input
52
+ #
53
+ # @return [Boolean]
54
+ #
55
+ # @api public
56
+ def required? = options.fetch(:required)
57
+
58
+ # Control whether the key is required
59
+ #
60
+ # @overload required
61
+ # @return [Boolean]
62
+ #
63
+ # @overload required(required)
64
+ # Change key's "requireness"
65
+ #
66
+ # @param [Boolean] required New value
67
+ # @return [Dry::Types::Schema::Key]
68
+ #
69
+ # @api public
70
+ def required(required = Undefined)
71
+ if Undefined.equal?(required)
72
+ options.fetch(:required)
73
+ else
74
+ with(required: required)
75
+ end
76
+ end
77
+
78
+ # Make key not required
79
+ #
80
+ # @return [Dry::Types::Schema::Key]
81
+ #
82
+ # @api public
83
+ def omittable = required(false)
84
+
85
+ # Turn key into a lax type. Lax types are not strict hence such keys are not required
86
+ #
87
+ # @return [Lax]
88
+ #
89
+ # @api public
90
+ def lax = __new__(type.lax).required(false)
91
+
92
+ # Make wrapped type optional
93
+ #
94
+ # @return [Key]
95
+ #
96
+ # @api public
97
+ def optional = __new__(type.optional)
98
+
99
+ # Dump to internal AST representation
100
+ #
101
+ # @return [Array]
102
+ #
103
+ # @api public
104
+ def to_ast(meta: true)
105
+ [
106
+ :key,
107
+ [
108
+ name,
109
+ required,
110
+ type.to_ast(meta: meta)
111
+ ]
112
+ ]
113
+ end
114
+
115
+ # @see Dry::Types::Meta#meta
116
+ #
117
+ # @api public
118
+ def meta(data = Undefined)
119
+ if Undefined.equal?(data) || !data.key?(:omittable)
120
+ super
121
+ else
122
+ self.class.warn(
123
+ "Using meta for making schema keys is deprecated, " \
124
+ "please use .omittable or .required(false) instead" \
125
+ "\n" + Core::Deprecations::STACK.()
126
+ )
127
+ super.required(!data[:omittable])
128
+ end
129
+ end
130
+
131
+ private
132
+
133
+ # @api private
134
+ def decorate?(response) = response.is_a?(Type)
135
+ end
136
+ end
137
+ end
138
+ end