openapi3_parser 0.8.2 → 0.9.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 (34) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/ci.yml +23 -0
  3. data/.rubocop.yml +18 -1
  4. data/.ruby-version +1 -1
  5. data/CHANGELOG.md +6 -0
  6. data/README.md +3 -3
  7. data/lib/openapi3_parser/array_sentence.rb +1 -1
  8. data/lib/openapi3_parser/error.rb +11 -1
  9. data/lib/openapi3_parser/node/context.rb +1 -3
  10. data/lib/openapi3_parser/node/placeholder.rb +8 -7
  11. data/lib/openapi3_parser/node_factory/map.rb +6 -6
  12. data/lib/openapi3_parser/node_factory/object_factory/dsl.rb +6 -4
  13. data/lib/openapi3_parser/node_factory/object_factory/field_config.rb +8 -7
  14. data/lib/openapi3_parser/node_factory/object_factory/node_builder.rb +11 -13
  15. data/lib/openapi3_parser/node_factory/object_factory/validator.rb +19 -17
  16. data/lib/openapi3_parser/node_factory/operation.rb +1 -3
  17. data/lib/openapi3_parser/node_factory/parameter_like.rb +1 -1
  18. data/lib/openapi3_parser/node_factory/reference.rb +1 -1
  19. data/lib/openapi3_parser/node_factory/request_body.rb +2 -4
  20. data/lib/openapi3_parser/source/pointer.rb +4 -4
  21. data/lib/openapi3_parser/source_input.rb +8 -10
  22. data/lib/openapi3_parser/source_input/file.rb +1 -1
  23. data/lib/openapi3_parser/source_input/raw.rb +1 -1
  24. data/lib/openapi3_parser/source_input/url.rb +1 -1
  25. data/lib/openapi3_parser/validation/error_collection.rb +1 -1
  26. data/lib/openapi3_parser/validation/input_validator.rb +1 -1
  27. data/lib/openapi3_parser/validators/component_keys.rb +1 -1
  28. data/lib/openapi3_parser/validators/email.rb +2 -2
  29. data/lib/openapi3_parser/validators/mutually_exclusive_fields.rb +6 -6
  30. data/lib/openapi3_parser/validators/url.rb +2 -7
  31. data/lib/openapi3_parser/version.rb +1 -1
  32. data/openapi3_parser.gemspec +6 -4
  33. metadata +45 -17
  34. data/.travis.yml +0 -22
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 370efdcfee85cad9520504280a4d34bddb5580df
4
- data.tar.gz: b28c58e9f45cf1c710f04d4b107d9e57c1502efa
2
+ SHA256:
3
+ metadata.gz: 81001258de6af8c21c8a7db87520d9433e3acb878483a56a616fdcd804e92848
4
+ data.tar.gz: 496f3a02ebcb386e949eab7ec6607f360a0b2e755be6bb4f1df3cd6b260a6e0d
5
5
  SHA512:
6
- metadata.gz: 41442d7730efd30d1e0d24dc78727f344c4ed46d37830cb205c9507d23190d39e1b88e6bd2691500e72d2647407c11242f321f6115bb40d46c5cfc1b6431fe9d
7
- data.tar.gz: c70c7b03895bfa441b1433acece362f0792c8436785361ac6b568bbe16866fba863d559f3c376149a958c1d3e2cde4f66cd50c53125203578e9397c798d23932
6
+ metadata.gz: d789d4ffe423f8854f961e902ffa6ef56b86d7dbcf506292106afa8548b72f2fbe968d98358ea7c80771a3c2e974c302096d43968c0663bdad40dc5f60a676e2
7
+ data.tar.gz: aea92fa77fbb4808872093b9149f8eb933f70a38336a0e415fa1fc9d4c15e691b8307abb0d70c0e51eee8eca89887cbc1a16b21e70f2d1812ae0fd77b75fe2a3
@@ -0,0 +1,23 @@
1
+ on: [push, pull_request]
2
+ jobs:
3
+ test:
4
+ strategy:
5
+ matrix:
6
+ ruby: [2.5, 2.6, 2.7, 3.0]
7
+ runs-on: ubuntu-latest
8
+ steps:
9
+ - uses: actions/checkout@v2
10
+ - uses: ruby/setup-ruby@v1
11
+ with:
12
+ bundler-cache: true
13
+ ruby-version: ${{ matrix.ruby }}
14
+ - name: Test Ruby ${{ matrix.ruby }}
15
+ run: bundle exec rake
16
+ if: matrix.ruby != '2.5'
17
+ - name: Test and publish coverage for Ruby ${{ matrix.ruby }}
18
+ uses: paambaati/codeclimate-action@v2.7.5
19
+ env:
20
+ CC_TEST_REPORTER_ID: 8bc2d8e54331569aeb442094c21cb64a58d6efa0670f65ff00d9ae887f63c0b4
21
+ with:
22
+ coverageCommand: bundle exec rake
23
+ if: matrix.ruby == '2.5'
data/.rubocop.yml CHANGED
@@ -1,13 +1,30 @@
1
+ require:
2
+ - rubocop-rake
3
+ - rubocop-rspec
4
+ AllCops:
5
+ NewCops: enable
1
6
  Style/StringLiterals:
2
7
  EnforcedStyle: double_quotes
3
8
  Metrics/MethodLength:
4
9
  Max: 30
5
10
  Metrics/AbcSize:
6
11
  Max: 30
12
+ RSpec/ExampleLength:
13
+ Max: 30
7
14
  Style/Documentation:
8
15
  Enabled: false
9
16
  Metrics/BlockLength:
10
17
  Exclude:
11
18
  - 'spec/**/*.rb'
12
- Style/BracesAroundHashParameters:
19
+ - '*.gemspec'
20
+ RSpec/DescribeClass:
21
+ Exclude:
22
+ - 'spec/integration/**/*.rb'
23
+ # I'd rather have multiple expectations than lots of duplicate tests
24
+ RSpec/MultipleExpectations:
25
+ Enabled: false
26
+ # The default arbitrary number (5) is a little painful
27
+ RSpec/MultipleMemoizedHelpers:
28
+ Enabled: false
29
+ RSpec/MessageSpies:
13
30
  Enabled: false
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.4.6
1
+ 2.5.8
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ # 0.9.0
2
+
3
+ - Fix unexpected fields error when using Example nodes inside a Parameter -
4
+ https://github.com/kevindew/openapi3_parser/pull/19
5
+ - Drop support for Ruby 2.4
6
+
1
7
  # 0.8.2
2
8
 
3
9
  - Fix bug falling into recursive loop on Array/Map nodes -
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # OpenAPI 3 Parser
2
2
 
3
- [![Build Status](https://travis-ci.org/kevindew/openapi3_parser.svg?branch=master)](https://travis-ci.org/kevindew/openapi3_parser)
3
+ [![Build Status](https://travis-ci.org/kevindew/openapi3_parser.svg?branch=main)](https://travis-ci.org/kevindew/openapi3_parser)
4
4
 
5
5
  This a Ruby based parser/validator for [OpenAPI 3][openapi-3]. It is used to
6
6
  convert an OpenAPI file (can be a local file, a URL, a string or even a Ruby
@@ -47,7 +47,7 @@ parser in [How to write an OpenAPI 3 parser][blog].
47
47
 
48
48
  ```ruby
49
49
  # by URL
50
- Openapi3Parser.load_url("https://raw.githubusercontent.com/kevindew/openapi3_parser/master/spec/support/examples/petstore-expanded.yaml")
50
+ Openapi3Parser.load_url("https://raw.githubusercontent.com/kevindew/openapi3_parser/main/spec/support/examples/petstore-expanded.yaml")
51
51
 
52
52
  # by path to file
53
53
  Openapi3Parser.load_file("spec/support/examples/uber.yaml")
@@ -76,7 +76,7 @@ document.errors
76
76
  ### Traversing
77
77
 
78
78
  ```ruby
79
- document = Openapi3Parser.load_url("https://raw.githubusercontent.com/kevindew/openapi3_parser/master/spec/support/examples/petstore-expanded.yaml")
79
+ document = Openapi3Parser.load_url("https://raw.githubusercontent.com/kevindew/openapi3_parser/main/spec/support/examples/petstore-expanded.yaml")
80
80
 
81
81
  # by objects
82
82
 
@@ -6,7 +6,7 @@ module Openapi3Parser
6
6
  def sentence_join
7
7
  return join if count < 2
8
8
 
9
- self[0..-2].join(", ") + " and " + self[-1]
9
+ "#{self[0..-2].join(', ')} and #{self[-1]}"
10
10
  end
11
11
  end
12
12
  end
@@ -7,32 +7,42 @@ module Openapi3Parser
7
7
  # at runtime when we have tried to access that resource it is not available
8
8
  # for whatever reason.
9
9
  class InaccessibleInput < Error; end
10
+
10
11
  # Raised in cases where we provided data that we expected to be parsable
11
12
  # (such as a string of JSON data) but when we tried to parse it an error
12
13
  # is raised
13
14
  class UnparsableInput < Error; end
15
+
14
16
  # Raised in cases where an object that is in an immutable state is modified
15
17
  #
16
18
  # Typically this would occur when a component that is frozen is modififed.
17
19
  # Some components are mutable during the construction of a document and
18
20
  # then frozen afterwards.
19
21
  class ImmutableObject < Error; end
20
- # Raised when a type that is not a whitelist of valid types is used
22
+
23
+ # Raised when a node is provided data as a type that is outside the allowed
24
+ # list
21
25
  class InvalidType < Error; end
26
+
22
27
  # Raised when we have to abort creating an object due to invalid data
23
28
  class InvalidData < Error; end
29
+
24
30
  # Used when there are fields that are missing from an object which prevents
25
31
  # us from creating a node
26
32
  class MissingFields < Error; end
33
+
27
34
  # Used when there are extra fields that are not expected in the data for
28
35
  # a node
29
36
  class UnexpectedFields < Error; end
37
+
30
38
  # Used when a method we expect to be able to call (through symbol or proc)
31
39
  # is not callable
32
40
  class NotCallable < Error; end
41
+
33
42
  # Raised when we in a recursive data structure and can't perform an
34
43
  # operation
35
44
  class InRecursiveStructure < Error; end
45
+
36
46
  # Used when we're trying to validate that a type is something that is not
37
47
  # validatable, most likely a sign that we're in a bug
38
48
  class UnvalidatableType < Error; end
@@ -107,9 +107,7 @@ module Openapi3Parser
107
107
  def location_summary
108
108
  summary = document_location.to_s
109
109
 
110
- if document_location != source_location
111
- summary += " (#{source_location})"
112
- end
110
+ summary += " (#{source_location})" if document_location != source_location
113
111
 
114
112
  summary
115
113
  end
@@ -21,8 +21,8 @@ module Openapi3Parser
21
21
  def self.each(node_data, &block)
22
22
  resolved =
23
23
  if node_data.respond_to?(:keys)
24
- node_data.each_with_object({}) do |(key, value), memo|
25
- memo[key] = resolve(value)
24
+ node_data.transform_values do |value|
25
+ resolve(value)
26
26
  end
27
27
  else
28
28
  node_data.map { |item| resolve(item) }
@@ -32,6 +32,7 @@ module Openapi3Parser
32
32
  end
33
33
 
34
34
  attr_reader :node_factory, :field, :parent_context
35
+
35
36
  def_delegators :node_factory, :nil_input?
36
37
 
37
38
  def initialize(node_factory, field, parent_context)
@@ -42,11 +43,11 @@ module Openapi3Parser
42
43
 
43
44
  def node
44
45
  @node ||= begin
45
- node_context = Context.next_field(parent_context,
46
- field,
47
- node_factory.context)
48
- node_factory.node(node_context)
49
- end
46
+ node_context = Context.next_field(parent_context,
47
+ field,
48
+ node_factory.context)
49
+ node_factory.node(node_context)
50
+ end
50
51
  end
51
52
  end
52
53
  end
@@ -90,12 +90,12 @@ module Openapi3Parser
90
90
  def build_resolved_input
91
91
  return unless data
92
92
 
93
- data.each_with_object({}) do |(key, value), memo|
94
- memo[key] = if value.respond_to?(:resolved_input)
95
- value.resolved_input
96
- else
97
- value
98
- end
93
+ data.transform_values do |value|
94
+ if value.respond_to?(:resolved_input)
95
+ value.resolved_input
96
+ else
97
+ value
98
+ end
99
99
  end
100
100
  end
101
101
 
@@ -1,12 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "ostruct"
4
3
  require "openapi3_parser/node_factory/object_factory/field_config"
5
4
 
6
5
  module Openapi3Parser
7
6
  module NodeFactory
8
7
  module ObjectFactory
9
8
  module Dsl
9
+ MutuallyExclusiveField = Struct.new(:fields, :required, keyword_init: true)
10
+
10
11
  def field(name, **options)
11
12
  @field_configs ||= {}
12
13
  @field_configs[name] = FieldConfig.new(**options)
@@ -30,8 +31,9 @@ module Openapi3Parser
30
31
 
31
32
  def mutually_exclusive(*fields, required: false)
32
33
  @mutually_exclusive_fields ||= []
33
- @mutually_exclusive_fields << OpenStruct.new(
34
- fields: fields, required: required
34
+ @mutually_exclusive_fields << MutuallyExclusiveField.new(
35
+ fields: fields,
36
+ required: required
35
37
  )
36
38
  end
37
39
 
@@ -41,7 +43,7 @@ module Openapi3Parser
41
43
 
42
44
  def validate(*items, &block)
43
45
  @validations ||= []
44
- @validations = @validations.concat(items)
46
+ @validations.concat(items)
45
47
  @validations << block if block
46
48
  end
47
49
 
@@ -22,10 +22,11 @@ module Openapi3Parser
22
22
  !given_factory.nil?
23
23
  end
24
24
 
25
- def initialize_factory(context, parent_factory)
26
- if given_factory.is_a?(Class)
25
+ def initialize_factory(context, parent_factory = nil)
26
+ case given_factory
27
+ when Class
27
28
  given_factory.new(context)
28
- elsif given_factory.is_a?(Symbol)
29
+ when Symbol
29
30
  parent_factory.send(given_factory, context)
30
31
  else
31
32
  given_factory.call(context)
@@ -36,7 +37,7 @@ module Openapi3Parser
36
37
  given_required
37
38
  end
38
39
 
39
- def check_input_type(validatable, building_node)
40
+ def check_input_type(validatable, building_node: false)
40
41
  return true if !given_input_type || validatable.input.nil?
41
42
 
42
43
  if building_node
@@ -47,7 +48,7 @@ module Openapi3Parser
47
48
  end
48
49
  end
49
50
 
50
- def validate_field(validatable, building_node)
51
+ def validate_field(validatable, building_node: false)
51
52
  return true if !given_validate || validatable.input.nil?
52
53
 
53
54
  run_validation(validatable)
@@ -61,9 +62,9 @@ module Openapi3Parser
61
62
  "Invalid data for #{location_summary}: #{error.message}"
62
63
  end
63
64
 
64
- def default(factory)
65
+ def default(factory = nil)
65
66
  return given_default.call if given_default.is_a?(Proc)
66
- return factory.send(given_default) if given_default.is_a?(Symbol)
67
+ return factory&.send(given_default) if given_default.is_a?(Symbol)
67
68
 
68
69
  given_default
69
70
  end
@@ -8,8 +8,8 @@ module Openapi3Parser
8
8
  new(factory).errors
9
9
  end
10
10
 
11
- def self.node_data(factory, parent_context)
12
- new(factory).node_data(parent_context)
11
+ def self.node_data(factory, node_context)
12
+ new(factory).node_data(node_context)
13
13
  end
14
14
 
15
15
  def initialize(factory)
@@ -22,19 +22,17 @@ module Openapi3Parser
22
22
 
23
23
  TypeChecker.validate_type(validatable, type: ::Hash)
24
24
 
25
- if validatable.errors.empty?
26
- validatable.add_errors(validate(raise_on_invalid: false))
27
- end
25
+ validatable.add_errors(validate(raise_on_invalid: false)) if validatable.errors.empty?
28
26
 
29
27
  validatable.collection
30
28
  end
31
29
 
32
- def node_data(parent_context)
33
- return build_node_data(parent_context) if empty_and_allowed_to_be?
30
+ def node_data(node_context)
31
+ return build_node_data(node_context) if empty_and_allowed_to_be?
34
32
 
35
33
  TypeChecker.raise_on_invalid_type(factory.context, type: ::Hash)
36
34
  validate(raise_on_invalid: true)
37
- build_node_data(parent_context)
35
+ build_node_data(node_context)
38
36
  end
39
37
 
40
38
  private_class_method :new
@@ -48,22 +46,22 @@ module Openapi3Parser
48
46
  end
49
47
 
50
48
  def validate(raise_on_invalid:)
51
- Validator.call(factory, raise_on_invalid)
49
+ Validator.call(factory, raise_on_invalid: raise_on_invalid)
52
50
  end
53
51
 
54
- def build_node_data(parent_context)
52
+ def build_node_data(node_context)
55
53
  return if factory.nil_input? && factory.data.nil?
56
54
 
57
55
  factory.data.each_with_object({}) do |(key, value), memo|
58
- memo[key] = resolve_value(key, value, parent_context)
56
+ memo[key] = resolve_value(key, value, node_context)
59
57
  end
60
58
  end
61
59
 
62
- def resolve_value(key, value, parent_context)
60
+ def resolve_value(key, value, node_context)
63
61
  resolved = determine_value_or_default(key, value)
64
62
 
65
63
  if resolved.respond_to?(:node)
66
- Node::Placeholder.new(value, key, parent_context)
64
+ Node::Placeholder.new(value, key, node_context)
67
65
  else
68
66
  resolved
69
67
  end
@@ -7,15 +7,15 @@ module Openapi3Parser
7
7
  module ObjectFactory
8
8
  class Validator
9
9
  private_class_method :new
10
- attr_reader :factory, :validatable, :building_node
10
+ attr_reader :factory, :validatable, :raise_on_invalid
11
11
 
12
- def self.call(*args)
13
- new(*args).call
12
+ def self.call(*args, **kwargs)
13
+ new(*args, **kwargs).call
14
14
  end
15
15
 
16
- def initialize(factory, building_node)
16
+ def initialize(factory, raise_on_invalid: false)
17
17
  @factory = factory
18
- @building_node = building_node
18
+ @raise_on_invalid = raise_on_invalid
19
19
  @validatable = Validation::Validatable.new(factory)
20
20
  end
21
21
 
@@ -34,7 +34,7 @@ module Openapi3Parser
34
34
  Validators::RequiredFields.call(
35
35
  validatable,
36
36
  required_fields: factory.required_fields,
37
- raise_on_invalid: building_node
37
+ raise_on_invalid: raise_on_invalid
38
38
  )
39
39
  end
40
40
 
@@ -43,7 +43,7 @@ module Openapi3Parser
43
43
  validatable,
44
44
  allow_extensions: factory.allowed_extensions?,
45
45
  allowed_fields: factory.allowed_fields,
46
- raise_on_invalid: building_node
46
+ raise_on_invalid: raise_on_invalid
47
47
  )
48
48
  end
49
49
 
@@ -51,7 +51,7 @@ module Openapi3Parser
51
51
  Validators::MutuallyExclusiveFields.call(
52
52
  validatable,
53
53
  mutually_exclusive_fields: factory.mutually_exclusive_fields,
54
- raise_on_invalid: building_node
54
+ raise_on_invalid: raise_on_invalid
55
55
  )
56
56
  end
57
57
 
@@ -66,7 +66,8 @@ module Openapi3Parser
66
66
  class CheckInvalidFields
67
67
  extend Forwardable
68
68
  attr_reader :validator
69
- def_delegators :validator, :factory, :building_node, :validatable
69
+
70
+ def_delegators :validator, :factory, :raise_on_invalid, :validatable
70
71
  private_class_method :new
71
72
 
72
73
  def self.call(validator)
@@ -88,16 +89,14 @@ module Openapi3Parser
88
89
 
89
90
  # We don't add errors when we're building a node as they will
90
91
  # be raised when that child node is built
91
- validatable.add_errors(field.errors) unless building_node
92
+ validatable.add_errors(field.errors) unless raise_on_invalid
92
93
  end
93
94
  end
94
95
 
95
96
  private
96
97
 
97
98
  def handle_factory_checks(name)
98
- field_errors = if factory.field_configs[name]
99
- check_field(name, factory.field_configs[name])
100
- end
99
+ field_errors = (check_field(name, factory.field_configs[name]) if factory.field_configs[name])
101
100
 
102
101
  (field_errors || []).any?
103
102
  end
@@ -115,11 +114,14 @@ module Openapi3Parser
115
114
  field_validatable = Validation::Validatable.new(factory,
116
115
  context: context)
117
116
 
118
- valid_input_type = field_config.check_input_type(field_validatable,
119
- building_node)
117
+ valid_input_type = field_config.check_input_type(
118
+ field_validatable,
119
+ building_node: raise_on_invalid
120
+ )
120
121
 
121
122
  if valid_input_type
122
- field_config.validate_field(field_validatable, building_node)
123
+ field_config.validate_field(field_validatable,
124
+ building_node: raise_on_invalid)
123
125
  end
124
126
 
125
127
  validatable.add_errors(field_validatable.errors)
@@ -139,7 +141,7 @@ module Openapi3Parser
139
141
 
140
142
  errors = validator.validatable.errors
141
143
 
142
- return if errors.empty? || !validator.building_node
144
+ return if errors.empty? || !validator.raise_on_invalid
143
145
 
144
146
  location_summary = errors.first.context.location_summary
145
147
  raise Error::InvalidData,
@@ -25,9 +25,7 @@ module Openapi3Parser
25
25
  private
26
26
 
27
27
  def build_object(data, context)
28
- if data["servers"].node.empty?
29
- data["servers"] = path_item_server_data(context)
30
- end
28
+ data["servers"] = path_item_server_data(context) if data["servers"].node.empty?
31
29
 
32
30
  Node::Operation.new(data, context)
33
31
  end
@@ -13,7 +13,7 @@ module Openapi3Parser
13
13
  end
14
14
 
15
15
  def examples_factory(context)
16
- factory = NodeFactory::OptionalReference.new(NodeFactory::Schema)
16
+ factory = NodeFactory::OptionalReference.new(NodeFactory::Example)
17
17
  NodeFactory::Map.new(context,
18
18
  default: nil,
19
19
  value_factory: factory)
@@ -44,7 +44,7 @@ module Openapi3Parser
44
44
 
45
45
  def build_node(node_context)
46
46
  TypeChecker.raise_on_invalid_type(context, type: ::Hash)
47
- ObjectFactory::Validator.call(self, true)
47
+ ObjectFactory::Validator.call(self, raise_on_invalid: true)
48
48
  data["$ref"].node(node_context)
49
49
  end
50
50
 
@@ -32,11 +32,9 @@ module Openapi3Parser
32
32
  def call(validatable)
33
33
  # This validation isn't actually mentioned in the spec, but it
34
34
  # doesn't seem to make sense if this is an empty hash.
35
- if validatable.input.size.zero?
36
- return validatable.add_error("Expected to have at least 1 item")
37
- end
35
+ return validatable.add_error("Expected to have at least 1 item") if validatable.input.size.zero?
38
36
 
39
- validatable.input.keys.each do |key|
37
+ validatable.input.each_key do |key|
40
38
  message = Validators::MediaType.call(key)
41
39
  next unless message
42
40
 
@@ -16,7 +16,7 @@ module Openapi3Parser
16
16
  unescaped = CGI.unescape(part.gsub("%20", "+"))
17
17
  unescaped.match?(/\A\d+\z/) ? unescaped.to_i : unescaped
18
18
  end
19
- new(segments.compact, absolute)
19
+ new(segments.compact, absolute: absolute)
20
20
  end
21
21
 
22
22
  def self.merge_pointers(base_pointer, new_pointer)
@@ -27,7 +27,7 @@ module Openapi3Parser
27
27
 
28
28
  # @param [::Array] segments
29
29
  # @param [Boolean] absolute
30
- def initialize(segments, absolute = true)
30
+ def initialize(segments, absolute: true)
31
31
  @segments = segments.freeze
32
32
  @absolute = absolute
33
33
  end
@@ -39,7 +39,7 @@ module Openapi3Parser
39
39
  def fragment
40
40
  fragment = segments.map { |s| CGI.escape(s.to_s).gsub("+", "%20") }
41
41
  .join("/")
42
- "#" + (absolute ? fragment.prepend("/") : fragment)
42
+ "##{absolute ? fragment.prepend('/') : fragment}"
43
43
  end
44
44
 
45
45
  def to_s
@@ -80,7 +80,7 @@ module Openapi3Parser
80
80
  def create_pointer(pointer_like)
81
81
  case pointer_like
82
82
  when Pointer then pointer_like
83
- when ::Array then Pointer.new(pointer_like, false)
83
+ when ::Array then Pointer.new(pointer_like, absolute: false)
84
84
  when ::String then Pointer.from_fragment(pointer_like)
85
85
  when nil then nil
86
86
  else raise Openapi3Parser::Error, "Unexpected type for pointer"
@@ -20,6 +20,14 @@ module Openapi3Parser
20
20
  class SourceInput
21
21
  attr_reader :access_error, :parse_error
22
22
 
23
+ def initialize
24
+ return if access_error
25
+
26
+ @contents = parse_contents
27
+ rescue ::StandardError => e
28
+ @parse_error = Error::UnparsableInput.new(e.message)
29
+ end
30
+
23
31
  # Indicates that the data within this input is suitable (i.e. can parse
24
32
  # underlying JSON or YAML) for trying to use as part of a Document
25
33
  def available?
@@ -57,15 +65,5 @@ module Openapi3Parser
57
65
  def relative_to(_source_input)
58
66
  ""
59
67
  end
60
-
61
- private
62
-
63
- def initialize_contents
64
- return if access_error
65
-
66
- @contents = parse_contents
67
- rescue ::StandardError => e
68
- @parse_error = Error::UnparsableInput.new(e.message)
69
- end
70
68
  end
71
69
  end
@@ -24,7 +24,7 @@ module Openapi3Parser
24
24
  @path = ::File.absolute_path(path)
25
25
  working_directory ||= resolve_working_directory
26
26
  @working_directory = ::File.absolute_path(working_directory)
27
- initialize_contents
27
+ super()
28
28
  end
29
29
 
30
30
  # @see SourceInput#resolve_next
@@ -26,7 +26,7 @@ module Openapi3Parser
26
26
  @base_url = base_url
27
27
  working_directory ||= resolve_working_directory
28
28
  @working_directory = ::File.absolute_path(working_directory)
29
- initialize_contents
29
+ super()
30
30
  end
31
31
 
32
32
  # @see SourceInput#resolve_next
@@ -17,7 +17,7 @@ module Openapi3Parser
17
17
  # @param [String, URI] request_url
18
18
  def initialize(request_url)
19
19
  @request_url = request_url.to_s
20
- initialize_contents
20
+ super()
21
21
  end
22
22
 
23
23
  # @see SourceInput#resolve_next
@@ -56,7 +56,7 @@ module Openapi3Parser
56
56
  grouped.each_with_object({}) do |(_, items), memo|
57
57
  items.each do |item|
58
58
  key = item.location_summary(with_type: items.count > 1)
59
- memo[key] = (memo[key] || []) + item.errors.map(&:to_s)
59
+ memo[key] = memo.fetch(key, []) + item.errors.map(&:to_s)
60
60
  end
61
61
  end
62
62
  end
@@ -10,7 +10,7 @@ module Openapi3Parser
10
10
  end
11
11
 
12
12
  def call(validatable)
13
- error = @callable.call(validatable.input)
13
+ error = callable.call(validatable.input)
14
14
  validatable.add_error(error) if error
15
15
  end
16
16
  end
@@ -6,7 +6,7 @@ module Openapi3Parser
6
6
  # defined for a Components node.
7
7
  # As defined: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.1.md#components-object
8
8
  class ComponentKeys
9
- REGEX = /\A[a-zA-Z0-9\.\-_]+\Z/.freeze
9
+ REGEX = /\A[a-zA-Z0-9.\-_]+\Z/.freeze
10
10
 
11
11
  def self.call(input)
12
12
  invalid = input.keys.reject { |key| REGEX.match(key) }
@@ -7,10 +7,10 @@ module Openapi3Parser
7
7
  # https://html.spec.whatwg.org/#e-mail-state-(type=email)
8
8
  REGEX = %r{
9
9
  \A
10
- [a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+
10
+ [a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+
11
11
  @
12
12
  [a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?
13
- (?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*
13
+ (?:.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*
14
14
  \Z
15
15
  }x.freeze
16
16
 
@@ -78,12 +78,12 @@ module Openapi3Parser
78
78
 
79
79
  def errors
80
80
  @errors ||= begin
81
- default = { required: [], exclusive: [] }
82
- mutually_exclusive_fields
83
- .each_with_object(default) do |exclusive, errors|
84
- add_error(errors, exclusive)
85
- end
86
- end
81
+ default = { required: [], exclusive: [] }
82
+ mutually_exclusive_fields
83
+ .each_with_object(default) do |exclusive, errors|
84
+ add_error(errors, exclusive)
85
+ end
86
+ end
87
87
  end
88
88
 
89
89
  private
@@ -4,14 +4,9 @@ module Openapi3Parser
4
4
  module Validators
5
5
  class Url
6
6
  def self.call(input)
7
- message = %("#{input}" is not a valid URL)
8
- uri = URI.parse(input)
9
-
10
- message if !uri.relative? &&
11
- !uri.is_a?(URI::HTTP) &&
12
- !uri.is_a?(URI::HTTPS)
7
+ URI.parse(input) && nil
13
8
  rescue URI::InvalidURIError
14
- message
9
+ %("#{input}" is not a valid URL)
15
10
  end
16
11
  end
17
12
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Openapi3Parser
4
- VERSION = "0.8.2"
4
+ VERSION = "0.9.0"
5
5
  end
@@ -24,16 +24,18 @@ Gem::Specification.new do |spec|
24
24
  f.match(%r{^spec/})
25
25
  end
26
26
 
27
- spec.required_ruby_version = ">= 2.4.0"
27
+ spec.required_ruby_version = ">= 2.5.0"
28
28
 
29
29
  spec.add_dependency "commonmarker", "~> 0.17"
30
30
  spec.add_dependency "psych", "~> 3.1"
31
31
 
32
32
  spec.add_development_dependency "bundler"
33
33
  spec.add_development_dependency "byebug", "~> 11.0"
34
- spec.add_development_dependency "rake", "~> 13.0"
34
+ spec.add_development_dependency "rake"
35
35
  spec.add_development_dependency "rspec", "~> 3.9"
36
- spec.add_development_dependency "rubocop", "~> 0.79.0"
37
- spec.add_development_dependency "simplecov", "~> 0.17"
36
+ spec.add_development_dependency "rubocop", "~> 1"
37
+ spec.add_development_dependency "rubocop-rake", "~> 0.5"
38
+ spec.add_development_dependency "rubocop-rspec", "~> 2"
39
+ spec.add_development_dependency "simplecov", "~> 0.19"
38
40
  spec.add_development_dependency "webmock", "~> 3.8"
39
41
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: openapi3_parser
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.2
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kevin Dew
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-06-13 00:00:00.000000000 Z
11
+ date: 2021-02-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: commonmarker
@@ -70,16 +70,16 @@ dependencies:
70
70
  name: rake
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - "~>"
73
+ - - ">="
74
74
  - !ruby/object:Gem::Version
75
- version: '13.0'
75
+ version: '0'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - "~>"
80
+ - - ">="
81
81
  - !ruby/object:Gem::Version
82
- version: '13.0'
82
+ version: '0'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: rspec
85
85
  requirement: !ruby/object:Gem::Requirement
@@ -100,28 +100,56 @@ dependencies:
100
100
  requirements:
101
101
  - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: 0.79.0
103
+ version: '1'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '1'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rubocop-rake
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '0.5'
104
118
  type: :development
105
119
  prerelease: false
106
120
  version_requirements: !ruby/object:Gem::Requirement
107
121
  requirements:
108
122
  - - "~>"
109
123
  - !ruby/object:Gem::Version
110
- version: 0.79.0
124
+ version: '0.5'
125
+ - !ruby/object:Gem::Dependency
126
+ name: rubocop-rspec
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '2'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '2'
111
139
  - !ruby/object:Gem::Dependency
112
140
  name: simplecov
113
141
  requirement: !ruby/object:Gem::Requirement
114
142
  requirements:
115
143
  - - "~>"
116
144
  - !ruby/object:Gem::Version
117
- version: '0.17'
145
+ version: '0.19'
118
146
  type: :development
119
147
  prerelease: false
120
148
  version_requirements: !ruby/object:Gem::Requirement
121
149
  requirements:
122
150
  - - "~>"
123
151
  - !ruby/object:Gem::Version
124
- version: '0.17'
152
+ version: '0.19'
125
153
  - !ruby/object:Gem::Dependency
126
154
  name: webmock
127
155
  requirement: !ruby/object:Gem::Requirement
@@ -145,11 +173,11 @@ executables: []
145
173
  extensions: []
146
174
  extra_rdoc_files: []
147
175
  files:
176
+ - ".github/workflows/ci.yml"
148
177
  - ".gitignore"
149
178
  - ".rspec"
150
179
  - ".rubocop.yml"
151
180
  - ".ruby-version"
152
- - ".travis.yml"
153
181
  - CHANGELOG.md
154
182
  - Gemfile
155
183
  - LICENCE
@@ -273,7 +301,7 @@ homepage: https://github.com/kevindew/openapi_parser
273
301
  licenses:
274
302
  - MIT
275
303
  metadata: {}
276
- post_install_message:
304
+ post_install_message:
277
305
  rdoc_options: []
278
306
  require_paths:
279
307
  - lib
@@ -281,16 +309,16 @@ required_ruby_version: !ruby/object:Gem::Requirement
281
309
  requirements:
282
310
  - - ">="
283
311
  - !ruby/object:Gem::Version
284
- version: 2.4.0
312
+ version: 2.5.0
285
313
  required_rubygems_version: !ruby/object:Gem::Requirement
286
314
  requirements:
287
315
  - - ">="
288
316
  - !ruby/object:Gem::Version
289
317
  version: '0'
290
318
  requirements: []
291
- rubyforge_project:
292
- rubygems_version: 2.6.14.4
293
- signing_key:
319
+ rubyforge_project:
320
+ rubygems_version: 2.7.6.2
321
+ signing_key:
294
322
  specification_version: 4
295
323
  summary: An OpenAPI V3 parser for Ruby
296
324
  test_files: []
data/.travis.yml DELETED
@@ -1,22 +0,0 @@
1
- language: ruby
2
- sudo: false
3
- env:
4
- global:
5
- CC_TEST_REPORTER_ID=8bc2d8e54331569aeb442094c21cb64a58d6efa0670f65ff00d9ae887f63c0b4
6
- CC_RUBY_VERSION=ruby-2.4.6
7
- rvm:
8
- - 2.4.6
9
- - 2.5.5
10
- - 2.6.4
11
- - 2.7.0
12
- - ruby-head
13
- matrix:
14
- allow_failures:
15
- - rvm: ruby-head
16
- fast_finish: true
17
- before_script:
18
- - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
19
- - chmod +x ./cc-test-reporter
20
- - if [ $(rvm current) = $CC_RUBY_VERSION ]; then ./cc-test-reporter before-build; fi
21
- after_script:
22
- - if [ $(rvm current) = $CC_RUBY_VERSION ]; then ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT; fi