nebius/SWE-rebench-V2-PRs huggingface dataset:
Repository: getkin/kin-openapi
Pull request #761 (2023-02-01 14:58:50)

openapi3: make `bad data ...` error more actionable
Signed-off-by: Pierre Fenoll <pierrefenoll@gmail.com>


Patch:
diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml
index 8dbb062..9d9ff72 100644
--- a/.github/workflows/go.yml
+++ b/.github/workflows/go.yml
@@ -176,6 +176,13 @@ jobs:
           Tag
           XML
 
+    - if: runner.os == 'Linux'
+      name: Ensure readableType() covers all possible values of resolved var
+      run: |
+        [[ "$(git grep -F 'var resolved ' -- openapi3/loader.go | awk '{print $4}' | sort | tr '\n' ' ')" = "$RESOLVEDS" ]]
+      env:
+        RESOLVEDS: 'Callback CallbackRef ExampleRef HeaderRef LinkRef ParameterRef PathItem RequestBodyRef ResponseRef SchemaRef SecuritySchemeRef '
+
   check-goimports:
     runs-on: ubuntu-latest
     steps:
diff --git a/openapi3/loader.go b/openapi3/loader.go
index 7f389cd..5102011 100644
--- a/openapi3/loader.go
+++ b/openapi3/loader.go
@@ -351,12 +351,41 @@ func (loader *Loader) resolveComponent(doc *T, ref string, path *url.URL, resolv
 			return nil
 		}
 		if err := codec(cursor, resolved); err != nil {
-			return nil, nil, fmt.Errorf("bad data in %q", ref)
+			return nil, nil, fmt.Errorf("bad data in %q (expecting %s)", ref, readableType(resolved))
 		}
 		return componentDoc, componentPath, nil
 
 	default:
-		return nil, nil, fmt.Errorf("bad data in %q", ref)
+		return nil, nil, fmt.Errorf("bad data in %q (expecting %s)", ref, readableType(resolved))
+	}
+}
+
+func readableType(x interface{}) string {
+	switch x.(type) {
+	case *Callback:
+		return "callback object"
+	case *CallbackRef:
+		return "ref to callback object"
+	case *ExampleRef:
+		return "ref to example object"
+	case *HeaderRef:
+		return "ref to header object"
+	case *LinkRef:
+		return "ref to link object"
+	case *ParameterRef:
+		return "ref to parameter object"
+	case *PathItem:
+		return "pathItem object"
+	case *RequestBodyRef:
+		return "ref to requestBody object"
+	case *ResponseRef:
+		return "ref to response object"
+	case *SchemaRef:
+		return "ref to schema object"
+	case *SecuritySchemeRef:
+		return "ref to securityScheme object"
+	default:
+		panic(fmt.Sprintf("unreachable %T", x))
 	}
 }
 


Test patch:
diff --git a/openapi3/issue759_test.go b/openapi3/issue759_test.go
new file mode 100644
index 0000000..255d8b7
--- /dev/null
+++ b/openapi3/issue759_test.go
@@ -0,0 +1,34 @@
+package openapi3
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/require"
+)
+
+func TestIssue759(t *testing.T) {
+	spec := []byte(`
+openapi: 3.0.0
+info:
+  title: title
+  description: description
+  version: 0.0.0
+paths:
+  /slash:
+    get:
+      responses:
+        "200":
+          # Ref should point to a response, not a schema
+          $ref: "#/components/schemas/UserStruct"
+components:
+  schemas:
+    UserStruct:
+      type: object
+`[1:])
+
+	loader := NewLoader()
+
+	doc, err := loader.LoadFromData(spec)
+	require.Nil(t, doc)
+	require.EqualError(t, err, `bad data in "#/components/schemas/UserStruct" (expecting ref to response object)`)
+}
Repository: getkin/kin-openapi
Pull request #792 (2023-05-10 08:00:50)

openapi3gen: fix panic when embedded type is not a struct
This PR fixes a panic when an embedded type is not a struct. 

To infer the actual type from the embedded type is specifically complex, it is simpler in these cases to use a schema customizer. It makes the most sense to ignore the type.


Patch:
diff --git a/openapi3gen/field_info.go b/openapi3gen/field_info.go
index 13f5ba0..8c03edb 100644
--- a/openapi3gen/field_info.go
+++ b/openapi3gen/field_info.go
@@ -23,6 +23,10 @@ func appendFields(fields []theFieldInfo, parentIndex []int, t reflect.Type) []th
 	if t.Kind() == reflect.Ptr {
 		t = t.Elem()
 	}
+	if t.Kind() != reflect.Struct {
+		return fields
+	}
+
 	// For each field
 	numField := t.NumField()
 iteration:


Test patch:
diff --git a/openapi3gen/openapi3gen_test.go b/openapi3gen/openapi3gen_test.go
index 9a143e4..553affc 100644
--- a/openapi3gen/openapi3gen_test.go
+++ b/openapi3gen/openapi3gen_test.go
@@ -24,6 +24,12 @@ func ExampleGenerator_SchemaRefs() {
 	type Embedded2 struct {
 		A string `json:"a"`
 	}
+	type EmbeddedNonStruct string
+	type EmbeddedNonStructPtr string
+	type Embedded3 struct {
+		EmbeddedNonStruct
+		*EmbeddedNonStructPtr
+	}
 	type SomeStruct struct {
 		Bool    bool                      `json:"bool"`
 		Int     int                       `json:"int"`
@@ -48,6 +54,8 @@ func ExampleGenerator_SchemaRefs() {
 
 		Embedded2
 
+		Embedded3 `json:"embedded3"`
+
 		Ptr *SomeOtherType `json:"ptr"`
 	}
 
@@ -64,7 +72,7 @@ func ExampleGenerator_SchemaRefs() {
 	}
 	fmt.Printf("schemaRef: %s\n", data)
 	// Output:
-	// g.SchemaRefs: 16
+	// g.SchemaRefs: 17
 	// schemaRef: {
 	//   "properties": {
 	//     "a": {
@@ -85,6 +93,7 @@ func ExampleGenerator_SchemaRefs() {
 	//       },
 	//       "type": "object"
 	//     },
+	//     "embedded3": {},
 	//     "float64": {
 	//       "format": "double",
 	//       "type": "number"
Repository: getkin/kin-openapi
Pull request #827 (2023-08-17 04:18:21)

openapi3: support patterned fields in Responses (#819)
Implements patterned fields in `openapi3.Responses.Get` 

This seemed to be the quickest fix for #819. Open to other ideas as well!


Patch:
diff --git a/openapi3/response.go b/openapi3/response.go
index 2035f46..b481ee1 100644
--- a/openapi3/response.go
+++ b/openapi3/response.go
@@ -27,8 +27,30 @@ func (responses Responses) Default() *ResponseRef {
 	return responses["default"]
 }
 
+// Get returns a ResponseRef for the given status
+// If an exact match isn't initially found a patterned field is checked using
+// the first digit to determine the range (eg: 201 to 2XX)
+// See https://spec.openapis.org/oas/v3.0.3#patterned-fields-0
 func (responses Responses) Get(status int) *ResponseRef {
-	return responses[strconv.FormatInt(int64(status), 10)]
+	st := strconv.FormatInt(int64(status), 10)
+	if rref, ok := responses[st]; ok {
+		return rref
+	}
+	st = string(st[0]) + "XX"
+	switch st {
+	case "1XX":
+		return responses["1XX"]
+	case "2XX":
+		return responses["2XX"]
+	case "3XX":
+		return responses["3XX"]
+	case "4XX":
+		return responses["4XX"]
+	case "5XX":
+		return responses["5XX"]
+	default:
+		return nil
+	}
 }
 
 // Validate returns an error if Responses does not comply with the OpenAPI spec.


Test patch:
diff --git a/openapi3/issue819_test.go b/openapi3/issue819_test.go
new file mode 100644
index 0000000..80f2136
--- /dev/null
+++ b/openapi3/issue819_test.go
@@ -0,0 +1,39 @@
+package openapi3
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/require"
+)
+
+func TestIssue819ResponsesGetPatternedFields(t *testing.T) {
+	spec := `
+openapi: "3.0.3"
+info:
+  title: 'My app'
+  version: 1.0.0
+  description: 'An API'
+
+paths:
+  /v1/operation:
+    get:
+      summary: Fetch something
+      responses:
+        2XX:
+          description: Success
+          content:
+            application/json:
+              schema:
+                type: object
+                description: An error response body.
+`[1:]
+	sl := NewLoader()
+	doc, err := sl.LoadFromData([]byte(spec))
+	require.NoError(t, err)
+	err = doc.Validate(sl.Context)
+	require.NoError(t, err)
+
+	require.NotNil(t, doc.Paths["/v1/operation"].Get.Responses.Get(201))
+	require.Nil(t, doc.Paths["/v1/operation"].Get.Responses.Get(404))
+	require.Nil(t, doc.Paths["/v1/operation"].Get.Responses.Get(999))
+}
Repository: getkin/kin-openapi
Pull request #848 (2023-10-17 05:50:23)

openapi2conv: fix that removes an extra `required` array from `formDataBody`
issue #847 


Patch:
diff --git a/openapi2conv/openapi2_conv.go b/openapi2conv/openapi2_conv.go
index c80e672..cb28247 100644
--- a/openapi2conv/openapi2_conv.go
+++ b/openapi2conv/openapi2_conv.go
@@ -339,6 +339,12 @@ func formDataBody(bodies map[string]*openapi3.SchemaRef, reqs map[string]bool, c
 			requireds = append(requireds, propName)
 		}
 	}
+	for s, ref := range bodies {
+		if ref.Value != nil && len(ref.Value.Required) > 0 {
+			ref.Value.Required = nil
+			bodies[s] = ref
+		}
+	}
 	schema := &openapi3.Schema{
 		Type:       "object",
 		Properties: ToV3Schemas(bodies),
@@ -701,7 +707,7 @@ func fromV3RequestBodies(name string, requestBodyRef *openapi3.RequestBodyRef, c
 		return
 	}
 
-	//Only select one formData or request body for an individual requestBody as OpenAPI 2 does not support multiples
+	// Only select one formData or request body for an individual requestBody as OpenAPI 2 does not support multiples
 	if requestBodyRef.Value != nil {
 		for contentType, mediaType := range requestBodyRef.Value.Content {
 			if consumes == nil {


Test patch:
diff --git a/openapi2conv/issue847_test.go b/openapi2conv/issue847_test.go
new file mode 100644
index 0000000..b4ea35d
--- /dev/null
+++ b/openapi2conv/issue847_test.go
@@ -0,0 +1,43 @@
+package openapi2conv
+
+import (
+	"context"
+	"testing"
+
+	"github.com/stretchr/testify/require"
+)
+
+func TestIssue847(t *testing.T) {
+	v2 := []byte(`
+swagger: '2.0'
+info:
+  version: '1.10'
+  title: title
+paths:
+  "/ping":
+    post:
+      consumes:
+      - multipart/form-data
+      parameters:
+      - name: file
+        in: formData
+        description: file
+        required: true
+        type: file
+      responses:
+        '200':
+          description: OK
+`)
+
+	v3, err := v2v3YAML(v2)
+	require.NoError(t, err)
+
+	err = v3.Validate(context.Background())
+	require.NoError(t, err)
+
+	schemaRequired := v3.Paths["/ping"].Post.RequestBody.Value.Content["multipart/form-data"].Schema.Value.Required
+	require.Equal(t, schemaRequired, []string{"file"})
+
+	fieldRequired := v3.Paths["/ping"].Post.RequestBody.Value.Content["multipart/form-data"].Schema.Value.Properties["file"].Value.Required
+	require.Nil(t, fieldRequired)
+}
Repository: getkin/kin-openapi
Pull request #852 (2023-10-27 02:10:31)

openAPI3 template T class add server helper function
open api add server helper functions
- T.Server.RemoveAllServers
- T.Server.AddServers 

simple unit tests for above 


Patch:
diff --git a/openapi3/openapi3.go b/openapi3/openapi3.go
index e488a59..4a855da 100644
--- a/openapi3/openapi3.go
+++ b/openapi3/openapi3.go
@@ -87,6 +87,10 @@ func (doc *T) AddServer(server *Server) {
 	doc.Servers = append(doc.Servers, server)
 }
 
+func (doc *T) AddServers(servers ...*Server) {
+	doc.Servers = append(doc.Servers, servers...)
+}
+
 // Validate returns an error if T does not comply with the OpenAPI spec.
 // Validations Options can be provided to modify the validation behavior.
 func (doc *T) Validate(ctx context.Context, opts ...ValidationOption) error {


Test patch:
diff --git a/openapi3/openapi3_test.go b/openapi3/openapi3_test.go
index 9a2714a..51073ab 100644
--- a/openapi3/openapi3_test.go
+++ b/openapi3/openapi3_test.go
@@ -7,6 +7,7 @@ import (
 	"testing"
 
 	"github.com/invopop/yaml"
+	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
 )
 
@@ -468,3 +469,37 @@ components:
 		})
 	}
 }
+
+func TestAddRemoveServer(t *testing.T) {
+	testServerLines := []*Server{{URL: "test0.com"}, {URL: "test1.com"}, {URL: "test3.com"}}
+
+	doc3 := &T{
+		OpenAPI:    "3.0.3",
+		Components: &Components{},
+	}
+
+	assert.Empty(t, doc3.Servers)
+
+	doc3.AddServer(&Server{URL: "testserver1.com"})
+
+	assert.NotEmpty(t, doc3.Servers)
+	assert.Len(t, doc3.Servers, 1)
+
+	doc3.Servers = Servers{}
+
+	assert.Empty(t, doc3.Servers)
+
+	doc3.AddServers(testServerLines[0], testServerLines[1], testServerLines[2])
+
+	assert.NotEmpty(t, doc3.Servers)
+	assert.Len(t, doc3.Servers, 3)
+
+	doc3.Servers = Servers{}
+
+	doc3.AddServers(testServerLines...)
+
+	assert.NotEmpty(t, doc3.Servers)
+	assert.Len(t, doc3.Servers, 3)
+
+	doc3.Servers = Servers{}
+}
Repository: getkin/kin-openapi
Pull request #872 (2023-11-26 15:39:39)

openapi3: fix validating extra siblings in remote refs


Patch:
diff --git a/openapi3/extension.go b/openapi3/extension.go
index c299590..37f6b01 100644
--- a/openapi3/extension.go
+++ b/openapi3/extension.go
@@ -8,11 +8,19 @@ import (
 )
 
 func validateExtensions(ctx context.Context, extensions map[string]interface{}) error { // FIXME: newtype + Validate(...)
+	allowed := getValidationOptions(ctx).extraSiblingFieldsAllowed
+
 	var unknowns []string
 	for k := range extensions {
-		if !strings.HasPrefix(k, "x-") {
-			unknowns = append(unknowns, k)
+		if strings.HasPrefix(k, "x-") {
+			continue
+		}
+		if allowed != nil {
+			if _, ok := allowed[k]; ok {
+				continue
+			}
 		}
+		unknowns = append(unknowns, k)
 	}
 
 	if len(unknowns) != 0 {


Test patch:
diff --git a/openapi3/issue513_test.go b/openapi3/issue513_test.go
index 332b922..442eac8 100644
--- a/openapi3/issue513_test.go
+++ b/openapi3/issue513_test.go
@@ -7,6 +7,71 @@ import (
 	"github.com/stretchr/testify/require"
 )
 
+func TestExtraSiblingsInRemoteRef(t *testing.T) {
+	spec := []byte(`
+openapi: 3.0.1
+servers:
+- url: http://localhost:5000
+info:
+  version: v1
+  title: Products api
+  contact:
+    name: me
+    email: me@github.com
+  description: This is a sample
+paths:
+  /categories:
+    get:
+      summary: Provides the available categories for the store
+      operationId: list-categories
+      responses:
+        '200':
+          description: this is a desc
+          content:
+            application/json:
+              schema:
+                $ref: http://schemas.sentex.io/store/categories.json
+`[1:])
+
+	// When that site fails to respond:
+	// see https://github.com/getkin/kin-openapi/issues/495
+
+	// http://schemas.sentex.io/store/categories.json
+	// {
+	//   "$id": "http://schemas.sentex.io/store/categories.json",
+	//   "$schema": "http://json-schema.org/draft-07/schema#",
+	//   "description": "array of category strings",
+	//   "type": "array",
+	//   "items": {
+	//     "allOf": [
+	//       {
+	//         "$ref": "http://schemas.sentex.io/store/category.json"
+	//       }
+	//     ]
+	//   }
+	// }
+
+	// http://schemas.sentex.io/store/category.json
+	// {
+	//   "$id": "http://schemas.sentex.io/store/category.json",
+	//   "$schema": "http://json-schema.org/draft-07/schema#",
+	//   "description": "category name for products",
+	//   "type": "string",
+	//   "pattern": "^[A-Za-z0-9\\-]+$",
+	//   "minimum": 1,
+	//   "maximum": 30
+	// }
+
+	sl := NewLoader()
+	sl.IsExternalRefsAllowed = true
+
+	doc, err := sl.LoadFromData(spec)
+	require.NoError(t, err)
+
+	err = doc.Validate(sl.Context, AllowExtraSiblingFields("$id", "$schema"))
+	require.NoError(t, err)
+}
+
 func TestIssue513OKWithExtension(t *testing.T) {
 	spec := `
 openapi: "3.0.3"
@@ -92,7 +157,7 @@ components:
 	require.ErrorContains(t, err, `extra sibling fields: [schema]`)
 }
 
-func TestIssue513KOMixesRefAlongWithOtherFields(t *testing.T) {
+func TestIssue513KOMixesRefAlongWithOtherFieldsDisallowed(t *testing.T) {
 	spec := `
 openapi: "3.0.3"
 info:
Repository: getkin/kin-openapi
Pull request #873 (2023-11-26 18:30:00)

openapi3: support \uC4FE codepoint syntax in Schema.Pattern


Patch:
diff --git a/openapi3/schema.go b/openapi3/schema.go
index c7041b5..f941a11 100644
--- a/openapi3/schema.go
+++ b/openapi3/schema.go
@@ -2011,22 +2011,6 @@ func (schema *Schema) expectedType(settings *schemaValidationSettings, value int
 	}
 }
 
-// NOTE: racey WRT [writes to schema.Pattern] vs [reads schema.Pattern then writes to compiledPatterns]
-func (schema *Schema) compilePattern() (cp *regexp.Regexp, err error) {
-	pattern := schema.Pattern
-	if cp, err = regexp.Compile(pattern); err != nil {
-		err = &SchemaError{
-			Schema:      schema,
-			SchemaField: "pattern",
-			Origin:      err,
-			Reason:      fmt.Sprintf("cannot compile pattern %q: %v", pattern, err),
-		}
-		return
-	}
-	var _ bool = compiledPatterns.CompareAndSwap(pattern, nil, cp)
-	return
-}
-
 // SchemaError is an error that occurs during schema validation.
 type SchemaError struct {
 	// Value is the value that failed validation.
diff --git a/openapi3/schema_pattern.go b/openapi3/schema_pattern.go
new file mode 100644
index 0000000..ceb4ad1
--- /dev/null
+++ b/openapi3/schema_pattern.go
@@ -0,0 +1,29 @@
+package openapi3
+
+import (
+	"fmt"
+	"regexp"
+)
+
+var patRewriteCodepoints = regexp.MustCompile(`[\][u]([0-9A-F]{4})`)
+
+// See https://pkg.go.dev/regexp/syntax
+func intoGoRegexp(re string) string {
+	return patRewriteCodepoints.ReplaceAllString(re, `x{$1}`)
+}
+
+// NOTE: racey WRT [writes to schema.Pattern] vs [reads schema.Pattern then writes to compiledPatterns]
+func (schema *Schema) compilePattern() (cp *regexp.Regexp, err error) {
+	pattern := schema.Pattern
+	if cp, err = regexp.Compile(intoGoRegexp(pattern)); err != nil {
+		err = &SchemaError{
+			Schema:      schema,
+			SchemaField: "pattern",
+			Origin:      err,
+			Reason:      fmt.Sprintf("cannot compile pattern %q: %v", pattern, err),
+		}
+		return
+	}
+	var _ bool = compiledPatterns.CompareAndSwap(pattern, nil, cp)
+	return
+}


Test patch:
diff --git a/openapi3/schema_pattern_test.go b/openapi3/schema_pattern_test.go
new file mode 100644
index 0000000..865a219
--- /dev/null
+++ b/openapi3/schema_pattern_test.go
@@ -0,0 +1,18 @@
+package openapi3
+
+import (
+	"regexp"
+	"testing"
+
+	"github.com/stretchr/testify/require"
+)
+
+func TestPattern(t *testing.T) {
+	_, err := regexp.Compile("^[a-zA-Z\\u0080-\\u024F\\s\\/\\-\\)\\(\\`\\.\\\"\\']+$")
+	require.EqualError(t, err, "error parsing regexp: invalid escape sequence: `\\u`")
+
+	_, err = regexp.Compile(`^[a-zA-Z\x{0080}-\x{024F}]+$`)
+	require.NoError(t, err)
+
+	require.Equal(t, `^[a-zA-Z\x{0080}-\x{024F}]+$`, intoGoRegexp(`^[a-zA-Z\u0080-\u024F]+$`))
+}
Repository: getkin/kin-openapi
Pull request #941 (2024-04-15 22:50:10)

openapi3: keep oneOf context in markSchemaErrorKey (#940)
https://github.com/getkin/kin-openapi/issues/940


Patch:
diff --git a/openapi3/schema.go b/openapi3/schema.go
index ae28afe..beac7ba 100644
--- a/openapi3/schema.go
+++ b/openapi3/schema.go
@@ -2119,14 +2119,16 @@ type SchemaError struct {
 var _ interface{ Unwrap() error } = SchemaError{}
 
 func markSchemaErrorKey(err error, key string) error {
-	var me multiErrorForOneOf
-
-	if errors.As(err, &me) {
-		err = me.Unwrap()
-	}
 
 	if v, ok := err.(*SchemaError); ok {
 		v.reversePath = append(v.reversePath, key)
+		if v.Origin != nil {
+			if unwrapped := errors.Unwrap(v.Origin); unwrapped != nil {
+				if me, ok := unwrapped.(multiErrorForOneOf); ok {
+					_ = markSchemaErrorKey(MultiError(me), key)
+				}
+			}
+		}
 		return v
 	}
 	if v, ok := err.(MultiError); ok {


Test patch:
diff --git a/openapi3/schema_issue940_test.go b/openapi3/schema_issue940_test.go
new file mode 100644
index 0000000..95d3d78
--- /dev/null
+++ b/openapi3/schema_issue940_test.go
@@ -0,0 +1,72 @@
+package openapi3
+
+import (
+	"context"
+	"encoding/json"
+	"errors"
+	"testing"
+
+	"github.com/stretchr/testify/require"
+)
+
+func TestOneOfErrorPreserved(t *testing.T) {
+
+	SchemaErrorDetailsDisabled = true
+	defer func() { SchemaErrorDetailsDisabled = false }()
+
+	// language=json
+	raw := `
+{
+	"foo": [ "bar" ]
+}
+`
+
+	// language=json
+	schema := `
+{
+	"type": "object",
+	"properties": {
+		"foo": {
+			"oneOf": [
+				{
+					"type": "number"
+				},
+					{
+					"type": "string"
+				}
+			]
+		}
+	}
+}
+`
+
+	s := NewSchema()
+	err := s.UnmarshalJSON([]byte(schema))
+	require.NoError(t, err)
+	err = s.Validate(context.Background())
+	require.NoError(t, err)
+
+	obj := make(map[string]interface{})
+	err = json.Unmarshal([]byte(raw), &obj)
+	require.NoError(t, err)
+
+	err = s.VisitJSON(obj, MultiErrors())
+	require.Error(t, err)
+
+	var multiError MultiError
+	ok := errors.As(err, &multiError)
+	require.True(t, ok)
+	var schemaErr *SchemaError
+	ok = errors.As(multiError[0], &schemaErr)
+	require.True(t, ok)
+
+	require.Equal(t, "oneOf", schemaErr.SchemaField)
+	require.Equal(t, `value doesn't match any schema from "oneOf"`, schemaErr.Reason)
+	require.Equal(t, `Error at "/foo": doesn't match schema due to: value must be a number Or value must be a string`, schemaErr.Error())
+
+	var me multiErrorForOneOf
+	ok = errors.As(err, &me)
+	require.True(t, ok)
+	require.Equal(t, `Error at "/foo": value must be a number`, me[0].Error())
+	require.Equal(t, `Error at "/foo": value must be a string`, me[1].Error())
+}
Repository: getkin/kin-openapi
Pull request #980 (2024-07-09 15:41:11)

fix: update type: file to type: string and format: binary
This PR addresses issue #979. It updates the "type: file" to "type: string" and "format: binary" when converting from V2 to V3 document. 


Patch:
diff --git a/openapi2conv/openapi2_conv.go b/openapi2conv/openapi2_conv.go
index 2e22f13..0a622f4 100644
--- a/openapi2conv/openapi2_conv.go
+++ b/openapi2conv/openapi2_conv.go
@@ -473,6 +473,9 @@ func ToV3SchemaRef(schema *openapi3.SchemaRef) *openapi3.SchemaRef {
 	if schema.Value.Items != nil {
 		schema.Value.Items = ToV3SchemaRef(schema.Value.Items)
 	}
+	if schema.Value.Type.Is("file") {
+		schema.Value.Format, schema.Value.Type = "binary", &openapi3.Types{"string"}
+	}
 	for k, v := range schema.Value.Properties {
 		schema.Value.Properties[k] = ToV3SchemaRef(v)
 	}


Test patch:
diff --git a/openapi2conv/issue979_test.go b/openapi2conv/issue979_test.go
new file mode 100644
index 0000000..8d87902
--- /dev/null
+++ b/openapi2conv/issue979_test.go
@@ -0,0 +1,68 @@
+package openapi2conv
+
+import (
+	"context"
+	"encoding/json"
+	"testing"
+
+	"github.com/stretchr/testify/require"
+
+	"github.com/getkin/kin-openapi/openapi2"
+	"github.com/getkin/kin-openapi/openapi3"
+)
+
+func TestIssue979(t *testing.T) {
+	v2 := []byte(`
+{
+    "basePath": "/v2",
+    "host": "test.example.com",
+    "info": {
+        "title": "MyAPI",
+        "version": "0.1",
+        "x-info": "info extension"
+    },
+    "paths": {
+        "/foo": {
+            "get": {
+                "operationId": "getFoo",
+                "produces": [
+                    "application/pdf",
+                    "application/json"
+                ],
+                "responses": {
+                    "200": {
+                        "description": "returns all information",
+                        "schema": {
+                            "type": "file"
+                        }
+                    },
+                    "default": {
+                        "description": "OK"
+                    }
+                },
+                "summary": "get foo"
+            }
+        }
+    },
+    "schemes": [
+        "http"
+    ],
+    "swagger": "2.0"
+}
+`)
+
+	var doc2 openapi2.T
+	err := json.Unmarshal(v2, &doc2)
+	require.NoError(t, err)
+
+	doc3, err := ToV3(&doc2)
+	require.NoError(t, err)
+	err = doc3.Validate(context.Background())
+	require.NoError(t, err)
+
+	require.Equal(t, &openapi3.Types{"string"}, doc3.Paths.Value("/foo").Get.Responses.Value("200").Value.Content.Get("application/json").Schema.Value.Type)
+	require.Equal(t, "binary", doc3.Paths.Value("/foo").Get.Responses.Value("200").Value.Content.Get("application/json").Schema.Value.Format)
+
+	require.Equal(t, &openapi3.Types{"string"}, doc3.Paths.Value("/foo").Get.Responses.Value("200").Value.Content.Get("application/pdf").Schema.Value.Type)
+	require.Equal(t, "binary", doc3.Paths.Value("/foo").Get.Responses.Value("200").Value.Content.Get("application/pdf").Schema.Value.Format)
+}