dry-schema 1.13.4 → 1.14.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +20 -0
  3. data/README.md +1 -1
  4. data/config/errors.yml +9 -1
  5. data/dry-schema.gemspec +15 -17
  6. data/lib/dry/schema/config.rb +6 -6
  7. data/lib/dry/schema/constants.rb +2 -2
  8. data/lib/dry/schema/dsl.rb +18 -18
  9. data/lib/dry/schema/extensions/hints/message_compiler_methods.rb +1 -1
  10. data/lib/dry/schema/extensions/info/schema_compiler.rb +16 -7
  11. data/lib/dry/schema/extensions/json_schema/schema_compiler.rb +3 -3
  12. data/lib/dry/schema/extensions/monads.rb +1 -1
  13. data/lib/dry/schema/extensions/struct.rb +3 -3
  14. data/lib/dry/schema/key.rb +4 -4
  15. data/lib/dry/schema/key_coercer.rb +3 -3
  16. data/lib/dry/schema/key_map.rb +5 -5
  17. data/lib/dry/schema/key_validator.rb +19 -8
  18. data/lib/dry/schema/macros/dsl.rb +8 -8
  19. data/lib/dry/schema/macros/each.rb +2 -2
  20. data/lib/dry/schema/macros/filled.rb +4 -5
  21. data/lib/dry/schema/macros/hash.rb +2 -2
  22. data/lib/dry/schema/macros/maybe.rb +2 -2
  23. data/lib/dry/schema/macros/schema.rb +3 -3
  24. data/lib/dry/schema/macros/value.rb +12 -12
  25. data/lib/dry/schema/message.rb +4 -4
  26. data/lib/dry/schema/message_compiler.rb +8 -8
  27. data/lib/dry/schema/message_set.rb +8 -8
  28. data/lib/dry/schema/messages/abstract.rb +12 -12
  29. data/lib/dry/schema/messages/namespaced.rb +1 -1
  30. data/lib/dry/schema/messages/template.rb +2 -2
  31. data/lib/dry/schema/messages/yaml.rb +3 -3
  32. data/lib/dry/schema/path.rb +12 -12
  33. data/lib/dry/schema/predicate.rb +4 -4
  34. data/lib/dry/schema/predicate_registry.rb +2 -2
  35. data/lib/dry/schema/processor.rb +10 -10
  36. data/lib/dry/schema/processor_steps.rb +1 -1
  37. data/lib/dry/schema/result.rb +6 -6
  38. data/lib/dry/schema/rule_applier.rb +1 -1
  39. data/lib/dry/schema/trace.rb +1 -1
  40. data/lib/dry/schema/type_container.rb +2 -2
  41. data/lib/dry/schema/type_registry.rb +1 -1
  42. data/lib/dry/schema/types.rb +1 -1
  43. data/lib/dry/schema/types_merger.rb +18 -62
  44. data/lib/dry/schema/value_coercer.rb +1 -1
  45. data/lib/dry/schema/version.rb +1 -1
  46. data/lib/dry/schema.rb +11 -11
  47. metadata +20 -78
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8a740c1cb0f62a33428ff5c187c9a93ce6fdd2dc567dd904f86e07d68d94f119
4
- data.tar.gz: b25d1dc73b7f6a2a7161a06495e4f1d5e4dfd6bafc52ad2a2088018fe9ecaf10
3
+ metadata.gz: c3e83fff26178481b1d8c4f4e3b5da6f1138268bf85123f59eb1806590217093
4
+ data.tar.gz: 865bcc2b635075227c513dbd54c2450f32a6d603ce734aa26f3be7a9d14dc8f4
5
5
  SHA512:
6
- metadata.gz: e914b3630c16022e6fb323a749ca66ad2dcff14ba24cff66f16b36fc102092ec9269d95e1f25dad3817eb4a44786d3a6a21d1fe7a930a75d63532a2fdcca663c
7
- data.tar.gz: d0436db384cf03b10eed4a20717de7f06c12fdfa94426af6bae7e92c93c88efcbc851ad658f0370add6fc0ebf1bad9b636fdc7d41faf75299da3c57fa947e767
6
+ metadata.gz: 2cc07bad04e6e1aeb9045fdca2dbd2c4f0aeaac3e541d0b8ce485c6eb03489e957e290ee57b3cb38570d77018c83bca8e7fc5f93ab5cec425592d52ff41dd189
7
+ data.tar.gz: 2265866e7fed3d481963450c7e9c928217482df3ac99820653a9e5007001344d4d3dbe6e66321faf6f193f4a37de20a185243a57c532464b68bc946b396617a9
data/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  <!--- DO NOT EDIT THIS FILE - IT'S AUTOMATICALLY GENERATED VIA DEVTOOLS --->
2
2
 
3
+ ## 1.14.0 2025-01-06
4
+
5
+
6
+ ### Added
7
+
8
+ - Better support for sets in `excluded_from?` and `included_in?` predicates (via #480) (@flash-gordon)
9
+
10
+ ### Fixed
11
+
12
+ - Fix info extension for maybe macro (via #484) (@flash-gordon + @santiagodoldan)
13
+ - Missing message for :uri? predicate (via #477) (@timjnh)
14
+ - JSON schema output for `maybe(:array)` (via #463) (@tomgi)
15
+
16
+ ### Changed
17
+
18
+ - Set minimum Ruby version to 3.1 (@flash-gordon)
19
+ - `KeyValidator` works faster for large schemas (via #461) (@radarek)
20
+
21
+ [Compare v1.13.4...v1.14.0](https://github.com/dry-rb/dry-schema/compare/v1.13.4...v1.14.0)
22
+
3
23
  ## 1.13.4 2024-05-22
4
24
 
5
25
 
data/README.md CHANGED
@@ -14,7 +14,7 @@
14
14
 
15
15
  This library officially supports the following Ruby versions:
16
16
 
17
- * MRI `>= 3.0.0`
17
+ * MRI `>= 3.1`
18
18
  * jruby `>= 9.4` (not tested on CI)
19
19
 
20
20
  ## License
data/config/errors.yml CHANGED
@@ -105,9 +105,17 @@ en:
105
105
  default: "must be %{size} bytes long"
106
106
  range: "must be within %{size_left} - %{size_right} bytes long"
107
107
 
108
+ uri?: "is not a valid URI"
109
+
110
+ uuid_v1?: "is not a valid UUID"
111
+
112
+ uuid_v2?: "is not a valid UUID"
113
+
114
+ uuid_v3?: "is not a valid UUID"
115
+
108
116
  uuid_v4?: "is not a valid UUID"
109
117
 
110
- uri?: "is not a valid URI"
118
+ uuid_v5?: "is not a valid UUID"
111
119
 
112
120
  not:
113
121
  empty?: "cannot be empty"
data/dry-schema.gemspec CHANGED
@@ -21,28 +21,26 @@ Gem::Specification.new do |spec|
21
21
 
22
22
  TEXT
23
23
  spec.homepage = "https://dry-rb.org/gems/dry-schema"
24
- spec.files = Dir["CHANGELOG.md", "LICENSE", "README.md", "dry-schema.gemspec", "lib/**/*", "config/*.yml"]
24
+ spec.files = Dir["CHANGELOG.md", "LICENSE", "README.md", "dry-schema.gemspec",
25
+ "lib/**/*", "config/*.yml"]
25
26
  spec.bindir = "bin"
26
27
  spec.executables = []
27
28
  spec.require_paths = ["lib"]
28
29
 
29
- spec.metadata["allowed_push_host"] = "https://rubygems.org"
30
- spec.metadata["changelog_uri"] = "https://github.com/dry-rb/dry-schema/blob/main/CHANGELOG.md"
31
- spec.metadata["source_code_uri"] = "https://github.com/dry-rb/dry-schema"
32
- spec.metadata["bug_tracker_uri"] = "https://github.com/dry-rb/dry-schema/issues"
30
+ spec.metadata["allowed_push_host"] = "https://rubygems.org"
31
+ spec.metadata["changelog_uri"] = "https://github.com/dry-rb/dry-schema/blob/main/CHANGELOG.md"
32
+ spec.metadata["source_code_uri"] = "https://github.com/dry-rb/dry-schema"
33
+ spec.metadata["bug_tracker_uri"] = "https://github.com/dry-rb/dry-schema/issues"
34
+ spec.metadata["rubygems_mfa_required"] = "true"
33
35
 
34
- spec.required_ruby_version = ">= 2.7"
36
+ spec.required_ruby_version = ">= 3.1"
35
37
 
36
38
  # to update dependencies edit project.yml
37
- spec.add_runtime_dependency "concurrent-ruby", "~> 1.0"
38
- spec.add_runtime_dependency "dry-configurable", "~> 1.0", ">= 1.0.1"
39
- spec.add_runtime_dependency "dry-core", "~> 1.0", "< 2"
40
- spec.add_runtime_dependency "dry-initializer", "~> 3.0"
41
- spec.add_runtime_dependency "dry-logic", ">= 1.4", "< 2"
42
- spec.add_runtime_dependency "dry-types", ">= 1.7", "< 2"
43
- spec.add_runtime_dependency "zeitwerk", "~> 2.6"
44
-
45
- spec.add_development_dependency "bundler"
46
- spec.add_development_dependency "rake"
47
- spec.add_development_dependency "rspec"
39
+ spec.add_dependency "concurrent-ruby", "~> 1.0"
40
+ spec.add_dependency "dry-configurable", "~> 1.0", ">= 1.0.1"
41
+ spec.add_dependency "dry-core", "~> 1.1"
42
+ spec.add_dependency "dry-initializer", "~> 3.2"
43
+ spec.add_dependency "dry-logic", "~> 1.5"
44
+ spec.add_dependency "dry-types", "~> 1.8"
45
+ spec.add_dependency "zeitwerk", "~> 2.6"
48
46
  end
@@ -12,8 +12,8 @@ module Dry
12
12
  #
13
13
  # @api public
14
14
  class Config
15
- include Dry::Configurable
16
- include Dry::Equalizer(:to_h, inspect: false)
15
+ include ::Dry::Configurable
16
+ include ::Dry::Equalizer(:to_h, inspect: false)
17
17
 
18
18
  # @!method predicates
19
19
  #
@@ -33,7 +33,7 @@ module Dry
33
33
  # @return [Hash]
34
34
  #
35
35
  # @api public
36
- setting :types, default: Dry::Types
36
+ setting :types, default: ::Dry::Types
37
37
 
38
38
  # @!method messages
39
39
  #
@@ -45,7 +45,7 @@ module Dry
45
45
  setting :messages do
46
46
  setting :backend, default: :yaml
47
47
  setting :namespace
48
- setting :load_paths, default: Set[DEFAULT_MESSAGES_PATH], constructor: :dup.to_proc
48
+ setting :load_paths, default: ::Set[DEFAULT_MESSAGES_PATH], constructor: :dup.to_proc
49
49
  setting :top_namespace, default: DEFAULT_MESSAGES_ROOT
50
50
  setting :default_locale
51
51
  end
@@ -74,9 +74,9 @@ module Dry
74
74
  # Forward to the underlying config object
75
75
  #
76
76
  # @api private
77
- def method_missing(meth, *args, &block)
77
+ def method_missing(meth, ...)
78
78
  super unless config.respond_to?(meth)
79
- config.public_send(meth, *args)
79
+ config.public_send(meth, ...)
80
80
  end
81
81
  end
82
82
  end
@@ -30,10 +30,10 @@ module Dry
30
30
  DEFAULT_MESSAGES_ROOT = "dry_schema"
31
31
 
32
32
  # An error raised when DSL is used in an incorrect way
33
- InvalidSchemaError = Class.new(StandardError)
33
+ InvalidSchemaError = ::Class.new(::StandardError)
34
34
 
35
35
  # An error raised when a localized message cannot be found
36
- MissingMessageError = Class.new(StandardError) do
36
+ MissingMessageError = ::Class.new(::StandardError) do
37
37
  # @api private
38
38
  def initialize(path, paths = [])
39
39
  *rest, rule = path
@@ -37,7 +37,7 @@ module Dry
37
37
  class DSL
38
38
  Types = Schema::Types
39
39
 
40
- extend Dry::Initializer
40
+ extend ::Dry::Initializer
41
41
 
42
42
  # @return [Compiler] The type of the processor (Params, JSON, or a custom sub-class)
43
43
  option :processor_type, default: -> { Processor }
@@ -78,9 +78,9 @@ module Dry
78
78
  # @return [DSL]
79
79
  #
80
80
  # @api public
81
- def self.new(**options, &block)
81
+ def self.new(**options, &)
82
82
  dsl = super
83
- dsl.instance_eval(&block) if block
83
+ dsl.instance_eval(&) if block_given?
84
84
  dsl.instance_variable_set("@compiler", options[:compiler]) if options[:compiler]
85
85
  dsl
86
86
  end
@@ -99,8 +99,8 @@ module Dry
99
99
  # @return [DSL]
100
100
  #
101
101
  # @api public
102
- def configure(&block)
103
- config.configure(&block)
102
+ def configure(&)
103
+ config.configure(&)
104
104
  self
105
105
  end
106
106
 
@@ -141,8 +141,8 @@ module Dry
141
141
  # @return [Macros::Required]
142
142
  #
143
143
  # @api public
144
- def required(name, &block)
145
- key(name, macro: Macros::Required, &block)
144
+ def required(name, &)
145
+ key(name, macro: Macros::Required, &)
146
146
  end
147
147
 
148
148
  # Define an optional key
@@ -157,8 +157,8 @@ module Dry
157
157
  # @return [Macros::Optional]
158
158
  #
159
159
  # @api public
160
- def optional(name, &block)
161
- key(name, macro: Macros::Optional, &block)
160
+ def optional(name, &)
161
+ key(name, macro: Macros::Optional, &)
162
162
  end
163
163
 
164
164
  # A generic method for defining keys
@@ -170,7 +170,7 @@ module Dry
170
170
  # @return [Macros::Key]
171
171
  #
172
172
  # @api public
173
- def key(name, macro:, &block)
173
+ def key(name, macro:, &)
174
174
  raise ArgumentError, "Key +#{name}+ is not a symbol" unless name.is_a?(::Symbol)
175
175
 
176
176
  set_type(name, Types::Any.meta(default: true))
@@ -182,7 +182,7 @@ module Dry
182
182
  filter_schema_dsl: filter_schema_dsl
183
183
  )
184
184
 
185
- macro.value(&block) if block
185
+ macro.value(&) if block_given?
186
186
  macros << macro
187
187
  macro
188
188
  end
@@ -249,8 +249,8 @@ module Dry
249
249
  # @return [DSL]
250
250
  #
251
251
  # @api public
252
- def before(key, &block)
253
- steps.before(key, &block)
252
+ def before(key, &)
253
+ steps.before(key, &)
254
254
  self
255
255
  end
256
256
 
@@ -264,8 +264,8 @@ module Dry
264
264
  # @return [DSL]
265
265
  #
266
266
  # @api public
267
- def after(key, &block)
268
- steps.after(key, &block)
267
+ def after(key, &)
268
+ steps.after(key, &)
269
269
  self
270
270
  end
271
271
 
@@ -301,8 +301,8 @@ module Dry
301
301
  # @return [Dry::Types::Safe]
302
302
  #
303
303
  # @api private
304
- def new(klass: self.class, **options, &block)
305
- klass.new(**options, processor_type: processor_type, config: config, &block)
304
+ def new(klass: self.class, **options, &)
305
+ klass.new(**options, processor_type: processor_type, config: config, &)
306
306
  end
307
307
 
308
308
  # Set a type for the given key name
@@ -501,7 +501,7 @@ module Dry
501
501
  def default_config
502
502
  parents.each_cons(2) do |left, right|
503
503
  unless left.config == right.config
504
- raise ArgumentError,
504
+ raise ::ArgumentError,
505
505
  "Parent configs differ, left=#{left.inspect}, right=#{right.inspect}"
506
506
  end
507
507
  end
@@ -31,7 +31,7 @@ module Dry
31
31
 
32
32
  # @api private
33
33
  def filter(messages, opts)
34
- Array(messages).flatten.map { |msg| msg unless exclude?(msg, opts) }.compact.uniq
34
+ Array(messages).flatten.reject { |msg| exclude?(msg, opts) }.uniq
35
35
  end
36
36
 
37
37
  # @api private
@@ -70,20 +70,25 @@ module Dry
70
70
 
71
71
  # @api private
72
72
  def visit_implication(node, opts = EMPTY_HASH)
73
- node.each do |el|
74
- visit(el, opts.merge(required: false))
73
+ case node
74
+ in [:not, [:predicate, [:nil?, _]]], el
75
+ visit(el, {**opts, nullable: true})
76
+ else
77
+ node.each do |el|
78
+ visit(el, {**opts, required: false})
79
+ end
75
80
  end
76
81
  end
77
82
 
78
83
  # @api private
79
84
  def visit_each(node, opts = EMPTY_HASH)
80
- visit(node, opts.merge(member: true))
85
+ visit(node, {**opts, member: true})
81
86
  end
82
87
 
83
88
  # @api private
84
89
  def visit_key(node, opts = EMPTY_HASH)
85
90
  name, rest = node
86
- visit(rest, opts.merge(key: name, required: true))
91
+ visit(rest, {**opts, key: name, required: true})
87
92
  end
88
93
 
89
94
  # @api private
@@ -93,19 +98,23 @@ module Dry
93
98
  key = opts[:key]
94
99
 
95
100
  if name.equal?(:key?)
96
- keys[rest[0][1]] = {required: opts.fetch(:required, true)}
101
+ keys[rest[0][1]] = {
102
+ required: opts.fetch(:required, true)
103
+ }
97
104
  else
98
105
  type = PREDICATE_TO_TYPE[name]
99
- assign_type(key, type) if type
106
+ nullable = opts.fetch(:nullable, false)
107
+ assign_type(key, type, nullable) if type
100
108
  end
101
109
  end
102
110
 
103
111
  # @api private
104
- def assign_type(key, type)
112
+ def assign_type(key, type, nullable)
105
113
  if keys[key][:type]
106
114
  keys[key][:member] = type
107
115
  else
108
116
  keys[key][:type] = type
117
+ keys[key][:nullable] = nullable
109
118
  end
110
119
  end
111
120
  end
@@ -9,7 +9,7 @@ module Dry
9
9
  # @api private
10
10
  class SchemaCompiler
11
11
  # An error raised when a predicate cannot be converted
12
- UnknownConversionError = Class.new(StandardError)
12
+ UnknownConversionError = ::Class.new(::StandardError)
13
13
 
14
14
  IDENTITY = ->(v, _) { v }.freeze
15
15
  TO_INTEGER = ->(v, _) { v.to_i }.freeze
@@ -97,7 +97,7 @@ module Dry
97
97
  target_info = opts[:member] ? {items: target.to_h} : target.to_h
98
98
  type = opts[:member] ? "array" : "object"
99
99
 
100
- keys.update(key => {**keys[key], type: type, **target_info})
100
+ merge_opts!(keys[key], {type: type, **target_info})
101
101
  end
102
102
 
103
103
  # @api private
@@ -210,7 +210,7 @@ module Dry
210
210
  orig_type = orig_opts[:type]
211
211
 
212
212
  if orig_type && new_type && orig_type != new_type
213
- new_opts[:type] = [orig_type, new_type]
213
+ new_opts[:type] = [orig_type, new_type].flatten.uniq
214
214
  end
215
215
 
216
216
  orig_opts.merge!(new_opts)
@@ -11,7 +11,7 @@ module Dry
11
11
  #
12
12
  # @api public
13
13
  class Result
14
- include Dry::Monads::Result::Mixin
14
+ include ::Dry::Monads::Result::Mixin
15
15
 
16
16
  # Turn result into a monad
17
17
  #
@@ -23,7 +23,7 @@ module Dry
23
23
  def call(*args)
24
24
  if args.size >= 1 && struct?(args[0])
25
25
  if block_given?
26
- raise ArgumentError, "blocks are not supported when using "\
26
+ raise ArgumentError, "blocks are not supported when using " \
27
27
  "a struct class (#{name.inspect} => #{args[0]})"
28
28
  end
29
29
 
@@ -44,7 +44,7 @@ module Dry
44
44
  })
45
45
  end
46
46
 
47
- PredicateInferrer::Compiler.send(:alias_method, :visit_struct, :visit_hash)
48
- PrimitiveInferrer::Compiler.send(:alias_method, :visit_struct, :visit_hash)
47
+ PredicateInferrer::Compiler.alias_method(:visit_struct, :visit_hash)
48
+ PrimitiveInferrer::Compiler.alias_method(:visit_struct, :visit_hash)
49
49
  end
50
50
  end
@@ -6,11 +6,11 @@ module Dry
6
6
  #
7
7
  # @api public
8
8
  class Key
9
- extend Dry::Core::Cache
9
+ extend ::Dry::Core::Cache
10
10
 
11
11
  DEFAULT_COERCER = :itself.to_proc.freeze
12
12
 
13
- include Dry.Equalizer(:name, :coercer)
13
+ include ::Dry.Equalizer(:name, :coercer)
14
14
 
15
15
  # @return [Symbol] The key identifier
16
16
  attr_reader :id
@@ -90,7 +90,7 @@ module Dry
90
90
  #
91
91
  # @api private
92
92
  class Hash < self
93
- include Dry.Equalizer(:name, :members, :coercer)
93
+ include ::Dry.Equalizer(:name, :members, :coercer)
94
94
 
95
95
  # @api private
96
96
  attr_reader :members
@@ -137,7 +137,7 @@ module Dry
137
137
  #
138
138
  # @api private
139
139
  class Array < self
140
- include Dry.Equalizer(:name, :member, :coercer)
140
+ include ::Dry.Equalizer(:name, :member, :coercer)
141
141
 
142
142
  attr_reader :member
143
143
 
@@ -9,7 +9,7 @@ module Dry
9
9
  #
10
10
  # @api private
11
11
  class KeyCoercer
12
- extend Dry::Core::Cache
12
+ extend ::Dry::Core::Cache
13
13
  include ::Dry::Equalizer(:key_map, :coercer)
14
14
 
15
15
  TO_SYM = :to_sym.to_proc.freeze
@@ -27,8 +27,8 @@ module Dry
27
27
  end
28
28
 
29
29
  # @api private
30
- def initialize(key_map, &coercer)
31
- @key_map = key_map.coercible(&coercer)
30
+ def initialize(key_map, &)
31
+ @key_map = key_map.coercible(&)
32
32
  end
33
33
 
34
34
  # @api private
@@ -13,10 +13,10 @@ module Dry
13
13
  #
14
14
  # @api public
15
15
  class KeyMap
16
- extend Dry::Core::Cache
16
+ extend ::Dry::Core::Cache
17
17
 
18
- include Dry.Equalizer(:keys)
19
- include Enumerable
18
+ include ::Dry.Equalizer(:keys)
19
+ include ::Enumerable
20
20
 
21
21
  # @return [Array<Key>] A list of defined key objects
22
22
  attr_reader :keys
@@ -105,8 +105,8 @@ module Dry
105
105
  # Iterate over keys
106
106
  #
107
107
  # @api public
108
- def each(&block)
109
- keys.each(&block)
108
+ def each(&)
109
+ keys.each(&)
110
110
  end
111
111
 
112
112
  # Return a new key map merged with the provided one
@@ -7,7 +7,7 @@ module Dry
7
7
  module Schema
8
8
  # @api private
9
9
  class KeyValidator
10
- extend Dry::Initializer
10
+ extend ::Dry::Initializer
11
11
 
12
12
  INDEX_REGEX = /\[\d+\]/
13
13
  DIGIT_REGEX = /\A\d+\z/
@@ -21,7 +21,7 @@ module Dry
21
21
  input = result.to_h
22
22
 
23
23
  input_paths = key_paths(input)
24
- key_paths = key_map.to_dot_notation
24
+ key_paths = key_map.to_dot_notation.sort
25
25
 
26
26
  input_paths.each do |path|
27
27
  error_path = validate_path(key_paths, path)
@@ -40,20 +40,31 @@ module Dry
40
40
  def validate_path(key_paths, path)
41
41
  if path[INDEX_REGEX]
42
42
  key = path.gsub(INDEX_REGEX, BRACKETS)
43
-
44
- if key_paths.none? { paths_match?(key, _1) }
43
+ if none_key_paths_match?(key_paths, key)
45
44
  arr = path.gsub(INDEX_REGEX) { ".#{_1[1]}" }
46
45
  arr.split(DOT).map { DIGIT_REGEX.match?(_1) ? Integer(_1, 10) : _1.to_sym }
47
46
  end
48
- elsif key_paths.none? { paths_match?(path, _1) }
47
+ elsif none_key_paths_match?(key_paths, path)
49
48
  path
50
49
  end
51
50
  end
52
51
 
53
52
  # @api private
54
- def paths_match?(input_path, key_path)
55
- residue = key_path.sub(input_path, "")
56
- residue.empty? || residue.start_with?(DOT, BRACKETS)
53
+ def none_key_paths_match?(key_paths, path)
54
+ !any_key_paths_match?(key_paths, path)
55
+ end
56
+
57
+ # @api private
58
+ def any_key_paths_match?(key_paths, path)
59
+ find_path(key_paths, path, false) ||
60
+ find_path(key_paths, path + DOT, true) ||
61
+ find_path(key_paths, path + BRACKETS, true)
62
+ end
63
+
64
+ # @api private
65
+ def find_path(key_paths, path, prefix_match)
66
+ key = key_paths.bsearch { |key_path| key_path >= path }
67
+ prefix_match ? key&.start_with?(path) : key == path
57
68
  end
58
69
 
59
70
  # @api private
@@ -7,7 +7,7 @@ module Dry
7
7
  #
8
8
  # @api public
9
9
  class DSL < Core
10
- include Dry::Logic::Operators
10
+ include ::Dry::Logic::Operators
11
11
 
12
12
  undef :eql?
13
13
  undef :nil?
@@ -52,15 +52,15 @@ module Dry
52
52
  # @return [Macros::Core]
53
53
  #
54
54
  # @api public
55
- def value(*args, **opts, &block)
55
+ def value(*args, **opts, &)
56
56
  if (type_spec_from_opts = opts[:type_spec])
57
57
  append_macro(Macros::Value) do |macro|
58
- macro.call(*args, type_spec: type_spec_from_opts, **opts, &block)
58
+ macro.call(*args, type_spec: type_spec_from_opts, **opts, &)
59
59
  end
60
60
  else
61
61
  extract_type_spec(args) do |*predicates, type_spec:, type_rule:|
62
62
  append_macro(Macros::Value) do |macro|
63
- macro.call(*predicates, type_spec: type_spec, type_rule: type_rule, **opts, &block)
63
+ macro.call(*predicates, type_spec: type_spec, type_rule: type_rule, **opts, &)
64
64
  end
65
65
  end
66
66
  end
@@ -77,10 +77,10 @@ module Dry
77
77
  # @return [Macros::Core]
78
78
  #
79
79
  # @api public
80
- def filled(*args, **opts, &block)
80
+ def filled(*args, **opts, &)
81
81
  extract_type_spec(args) do |*predicates, type_spec:, type_rule:|
82
82
  append_macro(Macros::Filled) do |macro|
83
- macro.call(*predicates, type_spec: type_spec, type_rule: type_rule, **opts, &block)
83
+ macro.call(*predicates, type_spec: type_spec, type_rule: type_rule, **opts, &)
84
84
  end
85
85
  end
86
86
  end
@@ -95,10 +95,10 @@ module Dry
95
95
  # @return [Macros::Key]
96
96
  #
97
97
  # @api public
98
- def maybe(*args, **opts, &block)
98
+ def maybe(*args, **opts, &)
99
99
  extract_type_spec(args, nullable: true) do |*predicates, type_spec:, type_rule:|
100
100
  append_macro(Macros::Maybe) do |macro|
101
- macro.call(*predicates, type_spec: type_spec, type_rule: type_rule, **opts, &block)
101
+ macro.call(*predicates, type_spec: type_spec, type_rule: type_rule, **opts, &)
102
102
  end
103
103
  end
104
104
  end
@@ -8,14 +8,14 @@ module Dry
8
8
  # @api private
9
9
  class Each < DSL
10
10
  # @api private
11
- def value(*args, **opts, &block)
11
+ def value(*args, **opts, &)
12
12
  extract_type_spec(args, set_type: false) do |*predicates, type_spec:, type_rule:|
13
13
  if type_spec && !type_spec.is_a?(Dry::Types::Type)
14
14
  type(schema_dsl.array[type_spec])
15
15
  end
16
16
 
17
17
  append_macro(Macros::Value) do |macro|
18
- macro.call(*predicates, type_spec: type_spec, type_rule: type_rule, **opts, &block)
18
+ macro.call(*predicates, type_spec: type_spec, type_rule: type_rule, **opts, &)
19
19
  end
20
20
  end
21
21
  end
@@ -8,17 +8,16 @@ module Dry
8
8
  # @api private
9
9
  class Filled < Value
10
10
  # @api private
11
- def call(*predicates, **opts, &block)
11
+ def call(*predicates, **opts, &)
12
12
  ensure_valid_predicates(predicates)
13
13
 
14
14
  append_macro(Macros::Value) do |macro|
15
15
  if opts[:type_spec] && !filter_empty_string?
16
- macro.call(predicates[0], :filled?, *predicates[1..predicates.size - 1], **opts,
17
- &block)
16
+ macro.call(predicates[0], :filled?, *predicates.drop(1), **opts, &)
18
17
  elsif opts[:type_rule]
19
- macro.call(:filled?).value(*predicates, **opts, &block)
18
+ macro.call(:filled?).value(*predicates, **opts, &)
20
19
  else
21
- macro.call(:filled?, *predicates, **opts, &block)
20
+ macro.call(:filled?, *predicates, **opts, &)
22
21
  end
23
22
  end
24
23
  end
@@ -8,7 +8,7 @@ module Dry
8
8
  # @api private
9
9
  class Hash < Schema
10
10
  # @api private
11
- def call(*args, &block)
11
+ def call(*args, &)
12
12
  if args.size >= 1 && args[0].respond_to?(:keys)
13
13
  hash_type = args[0]
14
14
  type_predicates = predicate_inferrer[hash_type]
@@ -21,7 +21,7 @@ module Dry
21
21
  else
22
22
  optional(key.name).value(key.type)
23
23
  end
24
- instance_exec(&block) if block
24
+ instance_exec(&) if block_given?
25
25
  end
26
26
  end
27
27
  else
@@ -8,7 +8,7 @@ module Dry
8
8
  # @api private
9
9
  class Maybe < DSL
10
10
  # @api private
11
- def call(*args, **opts, &block)
11
+ def call(*args, **opts, &)
12
12
  if args.include?(:empty?)
13
13
  raise ::Dry::Schema::InvalidSchemaError, "Using maybe with empty? predicate is invalid"
14
14
  end
@@ -18,7 +18,7 @@ module Dry
18
18
  end
19
19
 
20
20
  append_macro(Macros::Value) do |macro|
21
- macro.call(*args, **opts, &block)
21
+ macro.call(*args, **opts, &)
22
22
  end
23
23
 
24
24
  self