media_types 2.2.0 → 2.3.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 (44) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/debian.yml +43 -43
  3. data/.github/workflows/publish-bookworm.yml +33 -0
  4. data/.github/workflows/publish-sid.yml +33 -0
  5. data/.github/workflows/ruby.yml +22 -22
  6. data/.gitignore +20 -10
  7. data/.rubocop.yml +29 -29
  8. data/CHANGELOG.md +175 -164
  9. data/Gemfile +6 -6
  10. data/LICENSE +21 -21
  11. data/README.md +666 -664
  12. data/Rakefile +12 -12
  13. data/bin/console +15 -15
  14. data/bin/setup +8 -8
  15. data/lib/media_types/constructable.rb +161 -160
  16. data/lib/media_types/dsl/errors.rb +18 -18
  17. data/lib/media_types/dsl.rb +172 -172
  18. data/lib/media_types/errors.rb +25 -19
  19. data/lib/media_types/formatter.rb +56 -56
  20. data/lib/media_types/hash.rb +21 -21
  21. data/lib/media_types/object.rb +35 -35
  22. data/lib/media_types/scheme/allow_nil.rb +30 -30
  23. data/lib/media_types/scheme/any_of.rb +41 -41
  24. data/lib/media_types/scheme/attribute.rb +46 -46
  25. data/lib/media_types/scheme/enumeration_context.rb +18 -18
  26. data/lib/media_types/scheme/enumeration_of_type.rb +80 -80
  27. data/lib/media_types/scheme/errors.rb +87 -87
  28. data/lib/media_types/scheme/links.rb +54 -54
  29. data/lib/media_types/scheme/missing_validation.rb +41 -41
  30. data/lib/media_types/scheme/not_strict.rb +15 -15
  31. data/lib/media_types/scheme/output_empty_guard.rb +45 -45
  32. data/lib/media_types/scheme/output_iterator_with_predicate.rb +66 -66
  33. data/lib/media_types/scheme/output_type_guard.rb +39 -39
  34. data/lib/media_types/scheme/rules.rb +186 -173
  35. data/lib/media_types/scheme/rules_exhausted_guard.rb +73 -73
  36. data/lib/media_types/scheme/validation_options.rb +44 -43
  37. data/lib/media_types/scheme.rb +535 -513
  38. data/lib/media_types/testing/assertions.rb +20 -20
  39. data/lib/media_types/validations.rb +118 -105
  40. data/lib/media_types/version.rb +5 -5
  41. data/lib/media_types/views.rb +12 -12
  42. data/lib/media_types.rb +73 -73
  43. data/media_types.gemspec +33 -33
  44. metadata +8 -6
@@ -1,41 +1,41 @@
1
- # frozen_string_literal: true
2
-
3
- require 'media_types/scheme/errors'
4
-
5
- module MediaTypes
6
- class Scheme
7
- class MissingValidation
8
-
9
- def validate!(_output, options, context:, **_opts)
10
- # Check that no unknown keys are present
11
- return true unless options.strict
12
- raise_strict!(key: context.key, strict_keys: context.rules, backtrace: options.backtrace, found: options.scoped_output)
13
- end
14
-
15
- def raise_strict!(key:, backtrace:, strict_keys:, found:)
16
- raise StrictValidationError, format(
17
- "Unknown key %<key>s in data.\n" \
18
- "\tFound at: %<backtrace>s\n" \
19
- "\tExpected:\n\n" \
20
- "%<strict_keys>s\n\n" \
21
- "\tBut I Found:\n\n" \
22
- '%<found>s',
23
- key: key.inspect,
24
- backtrace: backtrace.join('->'),
25
- strict_keys: keys_to_str(strict_keys.keys),
26
- found: (found.respond_to? :keys) ? keys_to_str(found.keys) : found.class.name
27
- )
28
- end
29
-
30
- def inspect
31
- '((raise when strict))'
32
- end
33
-
34
- def keys_to_str(keys)
35
- converted = keys.map { |k| k.is_a?(Symbol) ? ":#{k}" : "'#{k}'" }
36
- "[#{converted.join ', '}]"
37
- end
38
-
39
- end
40
- end
41
- end
1
+ # frozen_string_literal: true
2
+
3
+ require 'media_types/scheme/errors'
4
+
5
+ module MediaTypes
6
+ class Scheme
7
+ class MissingValidation
8
+
9
+ def validate!(_output, options, context:, **_opts)
10
+ # Check that no unknown keys are present
11
+ return true unless options.strict
12
+ raise_strict!(key: context.key, strict_keys: context.rules, backtrace: options.backtrace, found: options.scoped_output)
13
+ end
14
+
15
+ def raise_strict!(key:, backtrace:, strict_keys:, found:)
16
+ raise StrictValidationError, format(
17
+ "Unknown key %<key>s in data.\n" \
18
+ "\tFound at: %<backtrace>s\n" \
19
+ "\tExpected:\n\n" \
20
+ "%<strict_keys>s\n\n" \
21
+ "\tBut I Found:\n\n" \
22
+ '%<found>s',
23
+ key: key.inspect,
24
+ backtrace: backtrace.join('->'),
25
+ strict_keys: keys_to_str(strict_keys.keys),
26
+ found: (found.respond_to? :keys) ? keys_to_str(found.keys) : found.class.name
27
+ )
28
+ end
29
+
30
+ def inspect
31
+ '((raise when strict))'
32
+ end
33
+
34
+ def keys_to_str(keys)
35
+ converted = keys.map { |k| k.is_a?(Symbol) ? ":#{k}" : "'#{k}'" }
36
+ "[#{converted.join ', '}]"
37
+ end
38
+
39
+ end
40
+ end
41
+ end
@@ -1,15 +1,15 @@
1
- # frozen_string_literal: true
2
-
3
- module MediaTypes
4
- class Scheme
5
- class NotStrict
6
- def validate!(*_args, **_opts)
7
- true
8
- end
9
-
10
- def inspect
11
- '((noop: not strict))'
12
- end
13
- end
14
- end
15
- end
1
+ # frozen_string_literal: true
2
+
3
+ module MediaTypes
4
+ class Scheme
5
+ class NotStrict
6
+ def validate!(*_args, **_opts)
7
+ true
8
+ end
9
+
10
+ def inspect
11
+ '((noop: not strict))'
12
+ end
13
+ end
14
+ end
15
+ end
@@ -1,45 +1,45 @@
1
- # frozen_string_literal: true
2
-
3
- require 'media_types/scheme/errors'
4
- require 'media_types/object'
5
-
6
- module MediaTypes
7
- class Scheme
8
- class OutputEmptyGuard
9
- class << self
10
- def call(*args, **opts, &block)
11
- new(*args, **opts).call(&block)
12
- end
13
- end
14
-
15
- def initialize(output, options, rules:)
16
- self.output = output
17
- self.options = options
18
- self.rules = rules
19
- end
20
-
21
- def call
22
- return unless MediaTypes::Object.new(output).empty?
23
- throw(:end, true) if allow_empty?
24
- raise_empty!(backtrace: options.backtrace, found: options.scoped_output)
25
- end
26
-
27
- private
28
-
29
- attr_accessor :output, :options, :rules
30
-
31
- def allow_empty?
32
- rules.allow_empty? || rules.required.empty?
33
- end
34
-
35
- def raise_empty!(backtrace:, found:)
36
- raise EmptyOutputError, format(
37
- 'Expected output, got empty at %<backtrace>s. Required are: %<required>s. Found: %<found>s',
38
- backtrace: backtrace.join('->'),
39
- required: rules.required.keys,
40
- found: (found.is_a? Hash) ? found.keys : found.class.name,
41
- )
42
- end
43
- end
44
- end
45
- end
1
+ # frozen_string_literal: true
2
+
3
+ require 'media_types/scheme/errors'
4
+ require 'media_types/object'
5
+
6
+ module MediaTypes
7
+ class Scheme
8
+ class OutputEmptyGuard
9
+ class << self
10
+ def call(*args, **opts, &block)
11
+ new(*args, **opts).call(&block)
12
+ end
13
+ end
14
+
15
+ def initialize(output, options, rules:)
16
+ self.output = output
17
+ self.options = options
18
+ self.rules = rules
19
+ end
20
+
21
+ def call
22
+ return unless MediaTypes::Object.new(output).empty?
23
+ throw(:end, true) if allow_empty?
24
+ raise_empty!(backtrace: options.backtrace, found: options.scoped_output)
25
+ end
26
+
27
+ private
28
+
29
+ attr_accessor :output, :options, :rules
30
+
31
+ def allow_empty?
32
+ rules.allow_empty? || rules.required(loose: options.loose).empty?
33
+ end
34
+
35
+ def raise_empty!(backtrace:, found:)
36
+ raise EmptyOutputError, format(
37
+ 'The object at %<backtrace>s was empty but I expected contents. Required keys are: %<required>s.',
38
+ backtrace: backtrace.join('->'),
39
+ required: rules.required(loose: options.loose).keys,
40
+ found: (found.respond_to? :keys) ? found.keys : found.class.name,
41
+ )
42
+ end
43
+ end
44
+ end
45
+ end
@@ -1,66 +1,66 @@
1
- # frozen_string_literal: true
2
-
3
- require 'media_types/scheme/enumeration_context'
4
-
5
- module MediaTypes
6
- class Scheme
7
- class OutputIteratorWithPredicate
8
-
9
- class << self
10
- def call(*args, **opts, &block)
11
- new(*args, **opts).call(&block)
12
- end
13
- end
14
-
15
- def initialize(enumerable, options, rules:)
16
- self.enumerable = enumerable
17
- self.options = options
18
- self.rules = rules
19
- end
20
-
21
- ##
22
- # Mimics Enumerable#all? with mandatory +&block+
23
- #
24
- def call
25
- if hash?
26
- return iterate_hash { |*args, **opts| yield(*args, **opts) }
27
- end
28
-
29
- if array?
30
- return iterate { |*args, **opts| yield(*args, **opts) }
31
- end
32
-
33
- raise "Internal consistency error, unexpected: #{enumerable.class}"
34
- end
35
-
36
- private
37
-
38
- attr_accessor :enumerable, :options, :rules
39
-
40
- def hash?
41
- enumerable.is_a?(::Hash) || enumerable.respond_to?(:key)
42
- end
43
-
44
- def array?
45
- enumerable.is_a?(::Array)
46
- end
47
-
48
- def iterate_hash
49
- context = EnumerationContext.new(rules: rules)
50
-
51
- enumerable.all? do |key, value|
52
- yield key, value, options: options, context: context.enumerate(key)
53
- end
54
- end
55
-
56
- def iterate(&block)
57
- hash_rule = Rules.new(allow_empty: false, expected_type: ::Hash)
58
-
59
- enumerable.each_with_index.all? do |array_like_element, i|
60
- OutputTypeGuard.call(array_like_element, options.trace(1), rules: hash_rule)
61
- OutputIteratorWithPredicate.call(array_like_element, options.trace(i), rules: rules, &block)
62
- end
63
- end
64
- end
65
- end
66
- end
1
+ # frozen_string_literal: true
2
+
3
+ require 'media_types/scheme/enumeration_context'
4
+
5
+ module MediaTypes
6
+ class Scheme
7
+ class OutputIteratorWithPredicate
8
+
9
+ class << self
10
+ def call(*args, **opts, &block)
11
+ new(*args, **opts).call(&block)
12
+ end
13
+ end
14
+
15
+ def initialize(enumerable, options, rules:)
16
+ self.enumerable = enumerable
17
+ self.options = options
18
+ self.rules = rules
19
+ end
20
+
21
+ ##
22
+ # Mimics Enumerable#all? with mandatory +&block+
23
+ #
24
+ def call
25
+ if hash?
26
+ return iterate_hash { |*args, **opts| yield(*args, **opts) }
27
+ end
28
+
29
+ if array?
30
+ return iterate { |*args, **opts| yield(*args, **opts) }
31
+ end
32
+
33
+ raise "Internal consistency error, unexpected: #{enumerable.class}"
34
+ end
35
+
36
+ private
37
+
38
+ attr_accessor :enumerable, :options, :rules
39
+
40
+ def hash?
41
+ enumerable.is_a?(::Hash) || enumerable.respond_to?(:key)
42
+ end
43
+
44
+ def array?
45
+ enumerable.is_a?(::Array)
46
+ end
47
+
48
+ def iterate_hash
49
+ context = EnumerationContext.new(rules: rules)
50
+
51
+ enumerable.all? do |key, value|
52
+ yield key, value, options: options, context: context.enumerate(key)
53
+ end
54
+ end
55
+
56
+ def iterate(&block)
57
+ hash_rule = Rules.new(allow_empty: false, expected_type: ::Hash)
58
+
59
+ enumerable.each_with_index.all? do |array_like_element, i|
60
+ OutputTypeGuard.call(array_like_element, options.trace(1), rules: hash_rule)
61
+ OutputIteratorWithPredicate.call(array_like_element, options.trace(i), rules: rules, &block)
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -1,39 +1,39 @@
1
- # frozen_string_literal: true
2
-
3
- require 'media_types/scheme/errors'
4
-
5
- module MediaTypes
6
- class Scheme
7
- class OutputTypeGuard
8
- class << self
9
- def call(*args, **opts, &block)
10
- new(*args, **opts).call(&block)
11
- end
12
- end
13
-
14
- def initialize(output, options, rules:)
15
- self.output = output
16
- self.options = options
17
- self.expected_type = rules.expected_type
18
- end
19
-
20
- def call
21
- return unless expected_type && !(expected_type === output) # rubocop:disable Style/CaseEquality
22
- raise_type_error!(type: output.class, backtrace: options.backtrace)
23
- end
24
-
25
- private
26
-
27
- attr_accessor :output, :options, :expected_type
28
-
29
- def raise_type_error!(type:, backtrace:)
30
- raise OutputTypeMismatch, format(
31
- 'Expected %<expected>s, got %<actual>s at %<backtrace>s',
32
- expected: expected_type,
33
- actual: type,
34
- backtrace: backtrace.join('->')
35
- )
36
- end
37
- end
38
- end
39
- end
1
+ # frozen_string_literal: true
2
+
3
+ require 'media_types/scheme/errors'
4
+
5
+ module MediaTypes
6
+ class Scheme
7
+ class OutputTypeGuard
8
+ class << self
9
+ def call(*args, **opts, &block)
10
+ new(*args, **opts).call(&block)
11
+ end
12
+ end
13
+
14
+ def initialize(output, options, rules:)
15
+ self.output = output
16
+ self.options = options
17
+ self.expected_type = rules.expected_type
18
+ end
19
+
20
+ def call
21
+ return unless expected_type && !(expected_type === output) # rubocop:disable Style/CaseEquality
22
+ raise_type_error!(type: output.class, backtrace: options.backtrace)
23
+ end
24
+
25
+ private
26
+
27
+ attr_accessor :output, :options, :expected_type
28
+
29
+ def raise_type_error!(type:, backtrace:)
30
+ raise OutputTypeMismatch, format(
31
+ 'Expected %<expected>s, got %<actual>s at %<backtrace>s',
32
+ expected: expected_type,
33
+ actual: type,
34
+ backtrace: backtrace.join('->')
35
+ )
36
+ end
37
+ end
38
+ end
39
+ end