openapi_parser 2.4.0 → 2.5.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d03c17295ee85e0cf17e06e83f6e28c1bed8028e7de1ae68574e2d69ad6160b2
4
- data.tar.gz: 6cae65df5bab290cff5d7c014d181f5eb631e153863f5eac82c7ce460d224dd9
3
+ metadata.gz: e570c33d05a24e9b11a3f5b86f5321f895088a672d404df68f3d14b4d3f9fb8f
4
+ data.tar.gz: fadcedd0e7b7c5ce057f2b0fa36f313218f151ae524dd2290c1242fbdfca02da
5
5
  SHA512:
6
- metadata.gz: 3074ba856acef7b064c0b1d2cf7b79b274e00766d90797ddfe95626f19ea09571fe72e2346e397bc7cac18f986959c659b62de2933b42d0a403074d5e41a73a9
7
- data.tar.gz: 7c373bb6e33c6bf221b7d3dbc41f89951109b8adc7bc9aef362eb5c820733e5c1203279c272e92e96b1cd4a6278b09f70aab5ffee809cf635e9253d6e616bb06
6
+ metadata.gz: 680325ae11c7dce38425d23c89918d3ce5cb768261dbd48f6d21c166ca0d89b2dbf9304297b2f754830f47cdf8d45dd2501371b396fe972957474e171f4b3b49
7
+ data.tar.gz: 27b757f70c102671ff1f2891918f5e7abb044796e280027b097214f4f0bbb2ff538b7f7c84d7d1bb7f1fc8b46b63591ad62e37985dab50ebb35c0603b854e92e
@@ -17,6 +17,7 @@ jobs:
17
17
  - "3.2"
18
18
  - "3.3"
19
19
  - "3.4"
20
+ - "4.0"
20
21
  - ruby-head
21
22
  runs-on: ${{ matrix.os }}
22
23
  steps:
data/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  ## Unreleased
2
2
 
3
+ ## 2.5.0 (2026-10-21)
4
+ * add OpenAPI 3.2 `SpecValidator` rules
5
+ * `SelfBefore32`: detect `$self` usage in pre-3.2 documents (3.2 addition)
6
+ * support root-level `$self` (OpenAPI 3.2) in the parse layer (`self_uri`); it is not yet used as the base URI for `$ref` resolution
7
+ * support boolean schemas (OpenAPI 3.1): `true` accepts any value and `false` rejects any value with `FalseSchemaError`, instead of crashing the loader with `NoMethodError`
8
+ * add `SpecValidator` rule `BooleanSchemaIn30`: detect boolean schemas in 3.0 documents (3.1 addition; `additionalProperties` is not affected)
9
+ * coerce non-String values into array-form `type` (3.1) the same way as a single `type` when `coerce_value` is on, so `type: [integer, "null"]` handles a Float the same way as `type: integer`
10
+ * stop truncating a Float with a fractional part in integer coercion (`coerce_value`): `1.5` for `type: integer` now fails instead of becoming `1`, while a Float with no fractional part, like `1.0`, is still converted
11
+
3
12
  ## 2.4.0 (2026-10-14)
4
13
  * support `components.pathItems` so `$ref`s into it resolve, unblocking OpenAPI 3.1 documents that use reusable path items
5
14
  * support array-form `type` (3.1) in value validation
@@ -38,6 +38,13 @@ module OpenAPIParser
38
38
  end
39
39
  end
40
40
 
41
+ # 3.1: raised for any value checked against the boolean schema `false`
42
+ class FalseSchemaError < OpenAPIError
43
+ def message
44
+ "#{@reference} does not allow any value"
45
+ end
46
+ end
47
+
41
48
  class NotExistRequiredKey < OpenAPIError
42
49
  def initialize(keys, reference)
43
50
  super(reference)
@@ -21,6 +21,8 @@ class OpenAPIParser::SchemaValidator
21
21
 
22
22
  def coerce(value)
23
23
  return value if value.kind_of?(Integer)
24
+ # Integer() truncates a Float, so convert only one with no fractional part.
25
+ return value.finite? && value == value.floor ? value.to_i : value if value.kind_of?(Float)
24
26
 
25
27
  begin
26
28
  Integer(value)
@@ -75,6 +75,13 @@ class OpenAPIParser::SchemaValidator
75
75
  def validate_schema(value, schema, **keyword_args)
76
76
  return [value, nil] unless schema
77
77
 
78
+ # 3.1: a boolean schema accepts (`true`) or rejects (`false`) any value,
79
+ # including null.
80
+ if schema.respond_to?(:raw_schema)
81
+ return [value, nil] if schema.raw_schema == true
82
+ return [nil, OpenAPIParser::FalseSchemaError.new(schema.object_reference)] if schema.raw_schema == false
83
+ end
84
+
78
85
  # 3.1: `const` pins the value to exactly that constant. Checked before
79
86
  # type dispatch so it applies uniformly across primitives. Detection
80
87
  # uses raw_schema so an intentional `const: null` is honored.
@@ -154,11 +161,14 @@ class OpenAPIParser::SchemaValidator
154
161
  end
155
162
  end
156
163
 
157
- # 3.1: request params arrive as Strings, so `type: [integer, "null"]`
158
- # never matches by class. When coercing, try each listed type instead.
164
+ # 3.1: when coercing, a value whose class matches no listed type is tried
165
+ # against each listed type, the same way a single `type` coerces it.
166
+ # Request params arrive as Strings ("5" for `type: [integer, "null"]`),
167
+ # and a single `type: integer` also coerces a Float such as 1.0.
168
+ # nil is left to the nil validator, as it is for a single `type`.
159
169
  # @return [Boolean]
160
170
  def coerce_into_type_array?(value, schema)
161
- return false unless @coerce_value && value.is_a?(String)
171
+ return false unless @coerce_value && !value.nil?
162
172
  return false if schema.any_of || schema.all_of || schema.one_of
163
173
 
164
174
  schema.type.is_a?(Array) && pick_array_type(value, schema.type).nil?
@@ -53,6 +53,10 @@ module OpenAPIParser::Schemas
53
53
  # @return [String, nil] dialect URI for embedded JSON Schemas (OpenAPI 3.1+)
54
54
  openapi_attr_value :json_schema_dialect, schema_key: :jsonSchemaDialect
55
55
 
56
+ # @!attribute [r] self_uri
57
+ # @return [String, nil] the document's own URI, `$self` (OpenAPI 3.2+)
58
+ openapi_attr_value :self_uri, schema_key: :'$self'
59
+
56
60
  # @return [OpenAPIParser::RequestOperation, nil]
57
61
  def request_operation(http_method, request_path)
58
62
  OpenAPIParser::RequestOperation.create(http_method, request_path, @path_item_finder, @config)
@@ -125,5 +125,13 @@ module OpenAPIParser::Schemas
125
125
  def additional_properties
126
126
  @additional_properties.nil? ? true : @additional_properties
127
127
  end
128
+
129
+ # 3.1: a boolean schema (`true` / `false`) has no keywords to load.
130
+ def load_data
131
+ return super if raw_schema.is_a?(::Hash)
132
+
133
+ @_openapi_all_child_objects = {}
134
+ nil
135
+ end
128
136
  end
129
137
  end
@@ -0,0 +1,26 @@
1
+ module OpenAPIParser
2
+ class SpecValidator
3
+ module Rules
4
+ # A boolean schema (`true` / `false` in place of a schema object) comes
5
+ # from JSON Schema 2020-12, which 3.1 adopts. 3.0 allows a boolean only
6
+ # for `additionalProperties`, which is not loaded as a Schema, so any
7
+ # Schema whose raw value is a boolean is a spec mismatch in 3.0.
8
+ class BooleanSchemaIn30 < Rule
9
+ def check(root)
10
+ return [] unless version_before?('3.1')
11
+
12
+ violations = []
13
+ each_schema(root) do |schema|
14
+ next unless schema.raw_schema == true || schema.raw_schema == false
15
+
16
+ violations << violation(
17
+ path: schema.object_reference,
18
+ message: 'a boolean schema is a 3.1 addition (from JSON Schema 2020-12); 3.0 allows a boolean only for `additionalProperties`',
19
+ )
20
+ end
21
+ violations
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,20 @@
1
+ module OpenAPIParser
2
+ class SpecValidator
3
+ module Rules
4
+ # `$self` is a 3.2 root-level addition declaring the document's own
5
+ # URI for reference resolution. The parse layer accepts it
6
+ # permissively; this rule reports the version mismatch.
7
+ class SelfBefore32 < Rule
8
+ def check(root)
9
+ return [] unless version_before?('3.2')
10
+ return [] unless root.raw_schema.is_a?(Hash) && root.raw_schema.key?('$self')
11
+
12
+ [violation(
13
+ path: '#/$self',
14
+ message: '`$self` is a 3.2 root-level addition; earlier documents have no such field',
15
+ )]
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -5,6 +5,7 @@ require_relative 'spec_validator/rules/exclusive_maximum'
5
5
  require_relative 'spec_validator/rules/content_encoding_in_30'
6
6
  require_relative 'spec_validator/rules/content_media_type_in_30'
7
7
  require_relative 'spec_validator/rules/prefix_items_in_30'
8
+ require_relative 'spec_validator/rules/boolean_schema_in_30'
8
9
  require_relative 'spec_validator/rules/json_schema_dialect_in_30'
9
10
  require_relative 'spec_validator/rules/type_array_in_30'
10
11
  require_relative 'spec_validator/rules/path_items_in_30'
@@ -16,6 +17,7 @@ require_relative 'spec_validator/rules/const_in_30'
16
17
  require_relative 'spec_validator/rules/dynamic_ref_in_30'
17
18
  require_relative 'spec_validator/rules/dynamic_anchor_in_30'
18
19
  require_relative 'spec_validator/rules/content_schema_in_30'
20
+ require_relative 'spec_validator/rules/self_before_32'
19
21
 
20
22
  module OpenAPIParser
21
23
  class SpecViolationError < OpenAPIError
@@ -68,6 +70,7 @@ module OpenAPIParser
68
70
  Rules::ContentEncodingIn30,
69
71
  Rules::ContentMediaTypeIn30,
70
72
  Rules::PrefixItemsIn30,
73
+ Rules::BooleanSchemaIn30,
71
74
  Rules::JsonSchemaDialectIn30,
72
75
  Rules::TypeArrayIn30,
73
76
  Rules::PathItemsIn30,
@@ -79,6 +82,7 @@ module OpenAPIParser
79
82
  Rules::DynamicRefIn30,
80
83
  Rules::DynamicAnchorIn30,
81
84
  Rules::ContentSchemaIn30,
85
+ Rules::SelfBefore32,
82
86
  ]
83
87
  end
84
88
  end
@@ -1,3 +1,3 @@
1
1
  module OpenAPIParser
2
- VERSION = '2.4.0'.freeze
2
+ VERSION = '2.5.0'.freeze
3
3
  end
@@ -59,6 +59,10 @@ module OpenAPIParser
59
59
  def check: (OpenAPIParser::Schemas::OpenAPI root) -> Array[SpecValidator::SpecViolation]
60
60
  end
61
61
 
62
+ class BooleanSchemaIn30 < Rule
63
+ def check: (OpenAPIParser::Schemas::OpenAPI root) -> Array[SpecValidator::SpecViolation]
64
+ end
65
+
62
66
  class JsonSchemaDialectIn30 < Rule
63
67
  def check: (OpenAPIParser::Schemas::OpenAPI root) -> Array[SpecValidator::SpecViolation]
64
68
  end
@@ -102,6 +106,10 @@ module OpenAPIParser
102
106
  class ContentSchemaIn30 < Rule
103
107
  def check: (OpenAPIParser::Schemas::OpenAPI root) -> Array[SpecValidator::SpecViolation]
104
108
  end
109
+
110
+ class SelfBefore32 < Rule
111
+ def check: (OpenAPIParser::Schemas::OpenAPI root) -> Array[SpecValidator::SpecViolation]
112
+ end
105
113
  end
106
114
  end
107
115
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: openapi_parser
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.0
4
+ version: 2.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ota42y
@@ -210,6 +210,7 @@ files:
210
210
  - lib/openapi_parser/schemas/schema.rb
211
211
  - lib/openapi_parser/spec_validator.rb
212
212
  - lib/openapi_parser/spec_validator/rule.rb
213
+ - lib/openapi_parser/spec_validator/rules/boolean_schema_in_30.rb
213
214
  - lib/openapi_parser/spec_validator/rules/const_in_30.rb
214
215
  - lib/openapi_parser/spec_validator/rules/content_encoding_in_30.rb
215
216
  - lib/openapi_parser/spec_validator/rules/content_media_type_in_30.rb
@@ -223,6 +224,7 @@ files:
223
224
  - lib/openapi_parser/spec_validator/rules/nullable_deprecation.rb
224
225
  - lib/openapi_parser/spec_validator/rules/path_items_in_30.rb
225
226
  - lib/openapi_parser/spec_validator/rules/prefix_items_in_30.rb
227
+ - lib/openapi_parser/spec_validator/rules/self_before_32.rb
226
228
  - lib/openapi_parser/spec_validator/rules/type_array_in_30.rb
227
229
  - lib/openapi_parser/spec_validator/rules/type_null_in_30.rb
228
230
  - lib/openapi_parser/spec_validator/rules/webhooks_in_30.rb